<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: James Oyanna</title>
    <description>The latest articles on Forem by James Oyanna (@jamesoyanna).</description>
    <link>https://forem.com/jamesoyanna</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F143149%2F278e47da-2551-4173-8bf9-cc6029a73cea.jpg</url>
      <title>Forem: James Oyanna</title>
      <link>https://forem.com/jamesoyanna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jamesoyanna"/>
    <language>en</language>
    <item>
      <title>Developing a fullstack E- commerce Application with Typescript. Part 1</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Sat, 14 Oct 2023 14:45:37 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/developing-a-fullstack-e-commerce-application-with-typescript-4ni6</link>
      <guid>https://forem.com/jamesoyanna/developing-a-fullstack-e-commerce-application-with-typescript-4ni6</guid>
      <description>&lt;p&gt;E-commerce application is like an online shopping mall on the internet. &lt;br&gt;
It lets you browse, select, and buy products online. You can shop from the comfort of your home, add items to a virtual cart, and complete your purchase with a click of a button. You can also make payment for a product using your debit or credit card.&lt;/p&gt;

&lt;p&gt;In this article, we'll be building a robust e-commerce application. &lt;/p&gt;

&lt;p&gt;We'll be working on both the frontend and backend, combining React and Node.js to create a seamless shopping experience.&lt;/p&gt;

&lt;p&gt;In this section we will be developing the backend of the e-commerce application. &lt;/p&gt;

&lt;p&gt;In part two of this article, we will be developing the &lt;code&gt;frontend&lt;/code&gt; of our e-commerce application.&lt;/p&gt;

&lt;p&gt;Now we will start by creating the backend of our e-commerce project. Make sure you have &lt;code&gt;nodejs&lt;/code&gt; installed on your system.&lt;/p&gt;

&lt;p&gt;Create a folder. Name it  &lt;code&gt;backend&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Next, we'll initialize our backend application by first setting-up the project &lt;code&gt;package.json&lt;/code&gt; and add the necessary dependencies.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting Up Node.js package.json:
&lt;/h3&gt;

&lt;p&gt;Then run the following command:&lt;br&gt;
 &lt;code&gt;npm init -y&lt;/code&gt;&lt;br&gt;
 to initialize a new project. Using the &lt;code&gt;-y&lt;/code&gt; flag when creating a &lt;code&gt;package.json&lt;/code&gt; will approve all the defaults.&lt;/p&gt;

&lt;p&gt;Now let's add Add &lt;code&gt;TypeScript&lt;/code&gt; as a &lt;code&gt;dev&lt;/code&gt; dependency by running this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install typescript --save-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let's add type definitions to our &lt;code&gt;Node.js&lt;/code&gt; application through its &lt;code&gt;@types/node&lt;/code&gt;package. &lt;/p&gt;

&lt;p&gt;This will enable us to write &lt;code&gt;TypeScript&lt;/code&gt; code that interacts with our Node.js APIs and modules in a type-safe manner.&lt;/p&gt;

&lt;p&gt;run this command:&lt;br&gt;
&lt;code&gt;npm install --save-dev @types/node&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a tsconfig.json file:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;tsconfig.json&lt;/code&gt; files serves as configuration file for &lt;code&gt;TypeScript&lt;/code&gt; compiler settings. &lt;/p&gt;

&lt;p&gt;Inside this file,  we will specify a variety of options to customize the behavior of the Typescript compiler according to our needs.&lt;br&gt;
Run the command:&lt;br&gt;
&lt;code&gt;npx tsc --init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will add a  &lt;code&gt;tsconfig.json&lt;/code&gt;  to the root of your backend folder. &lt;br&gt;
Remove the default configuration and the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here we setup a configuration file for typescript. We specify the ECMAScript target version to be es5.&lt;/p&gt;

&lt;p&gt;Now let's update our &lt;code&gt;package.json&lt;/code&gt; file and also add dependencies we will need for this project.&lt;/p&gt;

&lt;p&gt;Change the index.js file in the main section to this -&lt;code&gt;"main": "server.ts"&lt;/code&gt;,&lt;br&gt;
 Under the script section, add &lt;code&gt;"start": "nodemon server.ts"&lt;/code&gt;,&lt;/p&gt;

&lt;p&gt;Now let's add some of the dependencies we will be using for this project by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 npm i @types/bcryptjs @types/express @types/jsonwebtoken @types/mongoose @types/morgan @types/multer @types/supertest bcryptjs colors.ts cors express express-async-handler jsonwebtoken mongoose morgan multer @types/cors nodemon supertest @types/node dotenv ts-node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You install each package separately if you want.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;package.json&lt;/code&gt; file should now look like this. &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up the file structure:
&lt;/h3&gt;

&lt;p&gt;Now lets setup our file structure for our backend API. &lt;/p&gt;

&lt;p&gt;This will define how different components of our application will interact. &lt;br&gt;
This is to ensure the organization and maintainability of our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend
|-- config/
|   |-- db.ts
|-- controllers/
|   |-- orderController.ts
|   |-- userController.ts
|   |-- paystackController.ts
|   |-- productController.ts
|-- data/
|   |-- models/
|   |   |-- orders.ts
|   |   |-- products.ts
|   |   |-- users.ts
|   |   |-- reviews.ts
|   |-- db.ts
|-- middleware/
|   |-- authMiddleware.ts
|   |-- errorMiddleware.ts
|-- models/
|   |-- index.ts
|   |-- orderModel.ts
|   |-- productModel.ts
|   |-- userModel.ts
|-- routes/
|   |-- orderRoutes.ts
|   |-- paystackRoutes.ts
|   |-- productRoutes.ts
|   |-- uploadRoutes.ts
|   |-- userRoutes.ts
|-- types/
|   |-- express.ts
|   |-- index.ts
|   |-- order.ts
|   |-- product.ts
|   |-- user.ts
|-- uploads/
|   |-- image.png
|-- utils/
|   |-- generateToken.ts
|-- .env
|-- server.ts
|-- package.json
|-- seeder.ts
|-- tsconfig.json
|-- README.md

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's take a look at what the folders represents.&lt;br&gt;
&lt;strong&gt;config:&lt;/strong&gt; Contains configuration files including database configuration (database.ts).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;controllers:&lt;/strong&gt; Holds controller files responsible for handling different parts of our application routes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;models:&lt;/strong&gt; Contains Mongoose models (e.g., User.ts, Product.ts) that define the structure and shape of our database documents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;middleware:&lt;/strong&gt; It houses the &lt;code&gt;middleware&lt;/code&gt; functions that we will use in our application routes, such as authentication and validation and error &lt;code&gt;middleware&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;routes:&lt;/strong&gt; It defines the route files (e.g userRoutes.ts, productRoutes.ts) that specify the API endpoints and route handlers for various parts of our application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;types:&lt;/strong&gt; It contains the TypeScript type definitions (e.g., user.ts, product.d.ts) for data structures used in our API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;uploads:&lt;/strong&gt; We will use this folder to store temporary uploaded images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;utils:&lt;/strong&gt; We will use it to store utility functions or helper modules that we will use throughout our API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.env:&lt;/strong&gt; This file stores environment variables including sensitive configuration data and settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;server.ts:&lt;/strong&gt; This is the main entry point for our application. We will use it to set-up the Express server, load environment variables, configure routes and &lt;code&gt;middleware&lt;/code&gt;, and listen for incoming requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt;: Contains metadata about our API and its dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tsconfig.json:&lt;/strong&gt; The TypeScript configuration file that specifies how TypeScript should compile our code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting-up a simple server:
&lt;/h3&gt;

&lt;p&gt;Firstly, let us add a &lt;code&gt;.env&lt;/code&gt; file. We will use it to store configuration and sensitive information like database credentials that our application will need.&lt;/p&gt;

&lt;p&gt;In your root directory, create a file. Name it &lt;code&gt;.env&lt;/code&gt; and add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PORT = 5000&lt;/code&gt;&lt;br&gt;
Here, we added a port number that our application will listen on.&lt;/p&gt;

&lt;p&gt;Now let's create a simple server. &lt;br&gt;
Inside your &lt;code&gt;backend&lt;/code&gt; directory, create a file. Name it &lt;code&gt;server.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Here in this code above, we are setting up a basic &lt;code&gt;Node.js&lt;/code&gt; web server using the &lt;code&gt;Express.js&lt;/code&gt; framework. &lt;/p&gt;

&lt;p&gt;This server will serve as the foundation for building our e-commerce web API.&lt;/p&gt;

&lt;p&gt;We start by importing the necessary packages and modules. These include &lt;code&gt;express, cors, and morgan&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We then define a constant &lt;code&gt;PORT&lt;/code&gt; that represents the port number on which our server will listen. &lt;/p&gt;

&lt;p&gt;We determined this value by checking the &lt;code&gt;process.env.PORT&lt;/code&gt;environment variable. If &lt;code&gt;process.env.PORT&lt;/code&gt; is not defined (or falsy), we default to use port 4000.&lt;/p&gt;

&lt;p&gt;Next, we created an instance of the Express application by invoking &lt;code&gt;express()&lt;/code&gt;. Later, we will use this to configure our &lt;code&gt;routes&lt;/code&gt; and &lt;code&gt;middleware&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;cors&lt;/code&gt; middleware by calling &lt;code&gt;app.use(cors())&lt;/code&gt;. &lt;br&gt;
This &lt;code&gt;middleware&lt;/code&gt; enable Cross-Origin Resource Sharing (CORS).&lt;/p&gt;

&lt;p&gt;It will allow the server to respond to requests from different origins (domains).&lt;/p&gt;

&lt;p&gt;Next, we then configure the server to parse incoming JSON data from request bodies using &lt;code&gt;app.use(express.json())&lt;/code&gt;. &lt;br&gt;
This &lt;code&gt;middleware&lt;/code&gt; parses JSON data and make it accessible in the req.body object.&lt;/p&gt;

&lt;p&gt;Next, we set up request logging using the &lt;code&gt;morgan&lt;/code&gt; middleware. It logs&lt;code&gt;HTTP&lt;/code&gt; requests and responses to the console.&lt;/p&gt;

&lt;p&gt;We defined a single route using &lt;code&gt;app.get("/", ...)&lt;/code&gt; that handles GET requests to the root path ("/"). &lt;br&gt;
When a&lt;code&gt;GET&lt;/code&gt; request is made to this path, the server responds with the message "API IS RUNNING...".&lt;/p&gt;

&lt;p&gt;We started our application by calling &lt;code&gt;app.listen(PORT, ...)&lt;/code&gt;. &lt;br&gt;
It listens on the &lt;code&gt;PORT&lt;/code&gt; we defined earlier.&lt;/p&gt;
&lt;h3&gt;
  
  
  Connecting our API to a MongoDB Database:
&lt;/h3&gt;

&lt;p&gt;In this section, we will be establishing a connection to a database.&lt;/p&gt;

&lt;p&gt;To ensure that you have a MongoDB database instance set up and running, you'll need the connection &lt;code&gt;URI&lt;/code&gt; for your MongoDB database.&lt;/p&gt;

&lt;p&gt;You can either use a local MongoDB server or a cloud-based service like MongoDB Atlas. &lt;/p&gt;

&lt;p&gt;You can follow the steps in this article to install and use it locally on your system.-&lt;a href="https://www.freecodecamp.org/news/learn-mongodb-a4ce205e7739/"&gt; How to get started with MongoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have already installed the Mongoose package in our project during setup. &lt;/p&gt;

&lt;p&gt;If you are using a local setup of the MongoDB database on your project, create a database using the MongoDB compass copy your connection string and add it to your &lt;code&gt;.env&lt;/code&gt; file like this:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
MONGO_URI = mongodb://localhost:27017/commerce-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inside the root directory(i.e backend folder), create a folder. Name it &lt;code&gt;config&lt;/code&gt;. &lt;br&gt;
Inside it, create a file. name it &lt;code&gt;db.ts&lt;/code&gt; and add the following code:&lt;br&gt;
   &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we have a module responsible for connecting to a MongoDB database using the Mongoose library, which is a popular library for working with MongoDB in Node.js.

&lt;p&gt;We imported the &lt;code&gt;mongoose&lt;/code&gt; library, which allows us to interact with MongoDB.&lt;/p&gt;

&lt;p&gt;We then defined an &lt;code&gt;async&lt;/code&gt; function named &lt;code&gt;connectDB&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We are using this function to establish connection to the MongoDB database.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;connectDB&lt;/code&gt; function, we first check if the &lt;code&gt;MONGO_URI&lt;/code&gt;environment variable is defined in the &lt;code&gt;process.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;MONGO_URI&lt;/code&gt; environment variable is defined, then we connect to the database using &lt;code&gt;mongoose.connect&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This function returns a promise that resolves to a connection object (conn) when the connection is successful.&lt;/p&gt;

&lt;p&gt;We also check if an error occurs during the database connection attempt, we catch the error and log an error message. &lt;/p&gt;

&lt;p&gt;We call the &lt;code&gt;process.exit(1)&lt;/code&gt; to terminate our API process with an error exit code.&lt;/p&gt;

&lt;p&gt;Lastly, we exported the &lt;code&gt;connectDB&lt;/code&gt; function so it can be available to use in our &lt;code&gt;server.ts&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Now, let's make the database connection by importing the &lt;code&gt;connectDB&lt;/code&gt; function into our &lt;code&gt;server.ts&lt;/code&gt; file and then invoke it.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;server.ts&lt;/code&gt; file should now look like this:&lt;br&gt;
    &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this code, we have added two lines to configure environment variables and to establish a connection to the database.

&lt;p&gt;dotenv.config() : Here,we imported the &lt;code&gt;dotenv&lt;/code&gt; package and called its config() method. &lt;br&gt;
&lt;code&gt;dotenv&lt;/code&gt; is used to load environment variables from the &lt;code&gt;.env&lt;/code&gt; file into &lt;code&gt;process.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;connectDB()&lt;/strong&gt; : Here, we invoke the &lt;code&gt;connectDB&lt;/code&gt; function, which we imported from &lt;code&gt;"./config/db"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This initializes the connection to the MongoDB database. The &lt;code&gt;connectDB&lt;/code&gt; function is responsible for establising connecting to the database using the MongoDB URI we specified in our environment variables in this case, &lt;code&gt;MONGO_URI&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding Types:
&lt;/h3&gt;

&lt;p&gt;TypeScript types and interfaces are defined and used to enhance the type safety and readability of our &lt;code&gt;Express.js&lt;/code&gt; application. &lt;br&gt;
Let's add types for the express.&lt;br&gt;
Create a file inside the &lt;code&gt;types&lt;/code&gt; folder. Name it &lt;code&gt;express.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
 Here in this code, we we start by importing specific types (Request, Response, and NextFunction) from the "express" package.

&lt;p&gt;These types are used to describe the request, response, and next function that are commonly used in Express web applications. &lt;/p&gt;

&lt;p&gt;We use aliasing (as) to rename these types to Req, Res, and Next, respectively, for convenience.&lt;/p&gt;

&lt;p&gt;Next, we defined a custom TypeScript interface called &lt;code&gt;User&lt;/code&gt;. &lt;br&gt;
We use this interface to describe the structure of user-related data that can be attached to the Express request and response objects. &lt;/p&gt;

&lt;p&gt;It includes properties like _id (a string representing a unique identifier for the user), name (the user's name), email (the user's email address), and an optional property &lt;code&gt;isAdmin&lt;/code&gt; (a boolean indicating whether the user has administrative privileges).&lt;/p&gt;

&lt;p&gt;Finally, we create TypeScript type aliases (Request, Response, and NextFunction) that combine the imported Express types (Req, Res, Next) with the custom User interface.&lt;/p&gt;

&lt;p&gt;The Request and Response type alias combines the Req &amp;amp; Res type (representing an Express request and response object) with the User interface. &lt;/p&gt;

&lt;p&gt;This means that when you use &lt;code&gt;Request&lt;/code&gt; or &lt;code&gt;Response&lt;/code&gt; in your code, you'll have access to properties defined in the User interface in addition to the standard request or response properties.&lt;/p&gt;

&lt;p&gt;Now let's add the User types. Still inside the types folder, create a file. Name it &lt;code&gt;user.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we defined the TypeScript interfaces and types that we will use together with the Mongoose library to model and interact with user data in a MongoDB database:

&lt;p&gt;We start by defining an interface called &lt;code&gt;User&lt;/code&gt;. This describes the structure of a user document in our MongoDB database.&lt;/p&gt;

&lt;p&gt;It includes the name, email, password, and an optional &lt;code&gt;isAdmin&lt;/code&gt;flag. &lt;/p&gt;

&lt;p&gt;Next, we created an interface called &lt;code&gt;UserDocument&lt;/code&gt;, which extends the &lt;code&gt;User&lt;/code&gt; interface and Document type provided by Mongoose. &lt;/p&gt;

&lt;p&gt;This interface represents a document in our MongoDB collection that corresponds to a user. &lt;br&gt;
It inherits the properties from User and includes an additional method &lt;code&gt;matchPassword&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We will use this method to compare a provided password with the stored hashed password and return a Promise of type boolean.&lt;/p&gt;

&lt;p&gt;Lastly, we define an interface called &lt;code&gt;UserModel&lt;/code&gt;, which extends the &lt;code&gt;Model&lt;/code&gt; type from Mongoose and specifies that it works with documents of type &lt;code&gt;UserDocument&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We will add an &lt;code&gt;index.ts&lt;/code&gt; for exporting our types. Create a file in types folder. Name it &lt;code&gt;index.ts&lt;/code&gt; and add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export * from "./user";&lt;br&gt;
export * from "./express";&lt;/code&gt;&lt;br&gt;
The &lt;code&gt;index.ts&lt;/code&gt; file is using TypeScript's module exports to re-export modules and types from other files.&lt;/p&gt;

&lt;p&gt;Later, we will be adding other type definitions for our orders, products, etc.  For now, let us implement the user model.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing the User model:
&lt;/h3&gt;

&lt;p&gt;Inside the models folder, create a file, name it &lt;code&gt;userModel.ts&lt;/code&gt; and add the following code to it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we are defined and configured a Mongoose model for a user in our API that interacts with our database.

&lt;p&gt;We start by importing necessary dependencies. &lt;code&gt;bcrypt&lt;/code&gt; is used for hashing and comparing passwords securely. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;model&lt;/code&gt; and &lt;code&gt;Schema&lt;/code&gt; are from Mongoose, a MongoDB Object Data Modeling (ODM). &lt;br&gt;
We also imported &lt;code&gt;UserDocument&lt;/code&gt; from the &lt;code&gt;types&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;Then, we created a Mongoose schema (userSchema). This defines the structure of user documents in the MongoDB collection.&lt;/p&gt;

&lt;p&gt;It includes fields for name, email, password, and isAdmin, each with their respective data types and validation rules.&lt;/p&gt;

&lt;p&gt;We set the timestamps option to true, which automatically creates a &lt;code&gt;createdAt&lt;/code&gt; timestamp in each user document.&lt;/p&gt;

&lt;p&gt;We defined an instance method called &lt;code&gt;matchPassword&lt;/code&gt;. &lt;br&gt;
This method is available on user documents we created with this schema and we are using it to compare an entered password with the stored hashed password. &lt;br&gt;
It uses bcrypt.compare() for secure password comparison.&lt;/p&gt;

&lt;p&gt;We then defined a pre-save middleware. It runs before the user model is saved to the database.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;middleware&lt;/code&gt; checks if the user's password has been modified. If not, it calls the next function to proceed.&lt;/p&gt;

&lt;p&gt;If the password has been modified, it generates a salt and hashes the password using &lt;code&gt;bcrypt&lt;/code&gt; before saving it to the database. &lt;/p&gt;

&lt;p&gt;Finally, we created and exported the &lt;code&gt;User&lt;/code&gt; model. &lt;br&gt;
We will use this model to interact with the &lt;code&gt;"User"&lt;/code&gt; collection in the MongoDB database.&lt;/p&gt;

&lt;p&gt;To make all our models available across our application, create a file inside the models folder, name it &lt;code&gt;index.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { User } from "./userModel";
export { User };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here in this code, we are importing the User model and then re-exporting it from the current module. This means that any other module that imports from this module will have access to the User model as if it were defined in the current module.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing the Middlewares:
&lt;/h3&gt;

&lt;p&gt;Middlewares are functions or pieces of code that sit in between the HTTP request and the final response, allowing us to perform various tasks and operations on the request and response objects.&lt;br&gt;
We will be using it to authenticate, authorize, login, validate input and handle errors in our API.&lt;/p&gt;

&lt;p&gt;We will be adding the auth middleware. Inside your middleware folder, create a file, name it &lt;code&gt;authMiddleware.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Here in this code,we have two middleware functions, &lt;code&gt;protect&lt;/code&gt; and &lt;code&gt;admin&lt;/code&gt;, used to protect our routes and control access in our API&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;protect middleware&lt;/code&gt;to protect routes from unauthorized users. It's used for authentication and authorization purposes.&lt;/p&gt;

&lt;p&gt;It checks for the presence of a JSON Web Token (JWT) in the request's "Authorization" header. If a valid token is found, it decodes the token to retrieve user information.&lt;/p&gt;

&lt;p&gt;The user's information is then attached to the req object for future use. The properties attached to req.user include _id, name, email, and isAdmin.&lt;br&gt;
If the user is not found in the database, we return a 401 Unauthorized response and throws an error.&lt;/p&gt;

&lt;p&gt;If the token is invalid, we also return a 401 Unauthorized response and throws an error.&lt;br&gt;
If no token is found, we return a 401 Unauthorized response and throws an error.&lt;/p&gt;

&lt;p&gt;We use the admin &lt;code&gt;middleware&lt;/code&gt; to protect routes from users who are not flagged as administrators (admins).&lt;/p&gt;

&lt;p&gt;Firstly,we check if the user object is present on the req object, which is typically attached by the protect middleware, and whether the isAdmin property is set to true.&lt;/p&gt;

&lt;p&gt;If these conditions are met, it allows the request to continue processing by calling next().&lt;br&gt;
If the conditions are not met, we return a 401 Unauthorized response and throws an error, indicating that the user is not authorized as an admin.&lt;/p&gt;

&lt;p&gt;Now, let's add the &lt;code&gt;errorMiddleware&lt;/code&gt;. Inside the &lt;code&gt;middleware&lt;/code&gt; folder,create a file, name it &lt;code&gt;errorMiddleware.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this code, we have two &lt;code&gt;middleware&lt;/code&gt; functions, &lt;code&gt;notFound&lt;/code&gt; and &lt;code&gt;errorHandler&lt;/code&gt; to handle HTTP errors and error responses. 

&lt;p&gt;We use the &lt;code&gt;notFound&lt;/code&gt; middleware to handle situations where a requested route or resource is not found (HTTP 404 - Not Found).&lt;/p&gt;

&lt;p&gt;It takes three parameters: req (the request object), res (the response object), and next (the next function in the middleware chain).&lt;/p&gt;

&lt;p&gt;If a route is reached, and there is no matching route or resource for the requested URL (req.originalUrl), it generates a new error with a message indicating that the requested resource was not found.&lt;br&gt;
It sets the HTTP response status to 404 (Not Found) using res.status(404).&lt;br&gt;
Finally, it calls next(error) to pass the error to the next middleware in the chain.&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;errorHandler&lt;/code&gt; middleware is to handle and format error responses.&lt;br&gt;
It takes four parameters: err (the error object), req (the request object), res (the response object), and next (the next function in the middleware chain).&lt;/p&gt;

&lt;p&gt;It first determines the HTTP status code to use for the response. If the response status code is 200 (OK), it sets the status code to 500 (Internal Server Error); otherwise, it uses the existing status code.&lt;/p&gt;

&lt;p&gt;It sets the HTTP response status to the determined status code using res.status(statusCode).&lt;/p&gt;

&lt;p&gt;It sends a JSON response containing an error message (err.message) and, in development mode (when process.env.NODE_ENV is not "production"), the full error stack (err.stack).&lt;/p&gt;

&lt;p&gt;In production mode, the stack trace is omitted from the response for security reasons.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding Utility functions:
&lt;/h3&gt;

&lt;p&gt;Utility function are used to encapsulate common tasks or functionalities in a reusable and modular manner.&lt;br&gt;
Inside the &lt;code&gt;utils&lt;/code&gt; folder, create a file, name it &lt;code&gt;generateToken.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we have a utility file that contains a function for generating JSON Web Tokens (JWTs) for user authentication and authorization.

&lt;p&gt;We defined a function called &lt;code&gt;generateToken&lt;/code&gt;.&lt;br&gt;
This function is responsible for generating a JWT for a user.&lt;br&gt;
It takes a user's ID as a parameter. &lt;br&gt;
The ID is used as a payload in the JWT to uniquely identify the user.&lt;/p&gt;

&lt;p&gt;If the JWT_SECRET environment variable is defined (indicating the presence of a secret key for JWT generation), the function proceeds to create a JWT.&lt;/p&gt;

&lt;p&gt;It uses the &lt;code&gt;jwt.sign&lt;/code&gt; method provided by the &lt;code&gt;jsonwebtoken&lt;/code&gt; library to create a token.&lt;br&gt;
The token payload includes the user's ID.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;process.env.JWT_SECRET&lt;/code&gt; is used as the secret key for signing the token.&lt;/p&gt;

&lt;p&gt;The token is set to expire after 30 days (the expiresIn: "30d" option). The function returns the generated JWT&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing the User Controller:
&lt;/h3&gt;

&lt;p&gt;Now let's implement the user controller. Inside the controller folder, create a file. name it &lt;code&gt;userController.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this code, we have two route handler functions in a user controller. &lt;br&gt;
These functions handle user-related operations, such as authentication and registration, in our API.

&lt;p&gt;The &lt;code&gt;authUser&lt;/code&gt; function is responsible for user authentication.&lt;br&gt;
 It handles a POST request to the /api/users/login route.&lt;/p&gt;

&lt;p&gt;We firstly extract the email and password from the request body, submitted by a user attempting to log in.&lt;/p&gt;

&lt;p&gt;We then querie the database to find a user with the specified email using &lt;code&gt;User.findOne({ email })&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If a user is found, we proceed to check if the provided password matches the stored password using the matchPassword method.&lt;/p&gt;

&lt;p&gt;If the email and password match, it responds with a JSON object containing the user's information (e.g., user ID, name, email, and whether they are an admin) and a JSON Web Token (JWT) generated by the &lt;code&gt;generateToken&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;We will use this token to authenticate and authorize the user in subsequent requests.&lt;/p&gt;

&lt;p&gt;If the email and password do not match, we set the response status to 401 (Unauthorized) and throws an error, indicating that the login attempt is invalid.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;registerUser&lt;/code&gt; function handles user registration.&lt;br&gt;
It handles a POST request to the /api/users route, in our route.&lt;/p&gt;

&lt;p&gt;The function first extracts the name, email, and password from the request body, submitted by a user during registration.&lt;/p&gt;

&lt;p&gt;We first checks if a user with the provided email already exists by querying the database with &lt;code&gt;User.findOne({ email })&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If a user with the same email is found, we set the response status to 400 (Bad Request) and throws an error indicating that the user already exists.&lt;/p&gt;

&lt;p&gt;If the user does not already exist, we create a new user by calling &lt;code&gt;User.create&lt;/code&gt; with the provided user data.&lt;/p&gt;

&lt;p&gt;If the user creation is successful, we respond with a status of 201 (Created) and a JSON object containing the user's information and a JWT generated by the &lt;code&gt;generateToken&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;If user creation fails for any reason, we set the response status to 400 and throw an error indicating invalid user data.&lt;/p&gt;

&lt;p&gt;We then exported these functions to be used in our routes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding the UserRoutes:
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;routes&lt;/code&gt; folder, create a file. Name it &lt;code&gt;userRoutes.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we are setting up the routes related for user authentication and registration in our API.

&lt;p&gt;We imported the necessary modules, including express for creating a router, route handler functions from the &lt;code&gt;userController&lt;/code&gt;, and &lt;code&gt;middleware&lt;/code&gt; functions from the authMiddleware module.&lt;/p&gt;

&lt;p&gt;We created an instance of an Express router using express.Router() and assigned it to the router variable.&lt;/p&gt;

&lt;p&gt;We define several routes using the .route method on the router.&lt;br&gt;
&lt;code&gt;/ route&lt;/code&gt;: It's used for both registration and getting a list of all users. A POST request to this route invokes the registerUser function, which handles user registration.&lt;/p&gt;

&lt;p&gt;A GET request to this route invokes two &lt;code&gt;middleware&lt;/code&gt; functions, &lt;code&gt;protect&lt;/code&gt; and &lt;code&gt;admin&lt;/code&gt;, followed by an operation that gets a list of all users. &lt;/p&gt;

&lt;p&gt;We combined this to protect the route and ensure that only authenticated users with admin privileges can access it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/login route:&lt;/code&gt; This route handles user authentication.&lt;br&gt;
A POST request to this route invokes the &lt;code&gt;authUser&lt;/code&gt; function, which handles user authentication.&lt;/p&gt;

&lt;p&gt;The Middleware functions (protect and admin) are used in the route definitions to add an extra layer of logic before reaching the route handler. They perform tasks like user authentication and authorization.&lt;/p&gt;

&lt;p&gt;Lastly, we exported the router from this module, making it available for use in other parts of our application.&lt;/p&gt;

&lt;p&gt;Now, let's use our routes in the &lt;code&gt;server.ts&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;Update the code in the &lt;code&gt;server.ts&lt;/code&gt; file by importing and adding the routes.&lt;br&gt;
The updated server.ts file should now look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Test your endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the product Types:
&lt;/h3&gt;

&lt;p&gt;In your types folder, create a file. Name it product.ts and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here In this code, we are defining the data models and interfaces for products and product reviews in our API. 

&lt;p&gt;We are simply defining TypeScript interfaces for products and product reviews, which we are using to specify the shape of data objects in our database.&lt;/p&gt;

&lt;p&gt;The Product interface represents a product and defines the following properties:&lt;br&gt;
&lt;strong&gt;name:&lt;/strong&gt; The name of the product.&lt;br&gt;
&lt;strong&gt;image:&lt;/strong&gt; A URL or path to the product's image.&lt;br&gt;
description: A description of the product.&lt;br&gt;
&lt;strong&gt;brand:&lt;/strong&gt; The brand or manufacturer of the product.&lt;br&gt;
&lt;strong&gt;category:&lt;/strong&gt; The category to which the product belongs.&lt;br&gt;
&lt;strong&gt;price:&lt;/strong&gt; The price of the product.&lt;br&gt;
&lt;strong&gt;countInStock:&lt;/strong&gt; The number of items available in stock.&lt;br&gt;
&lt;strong&gt;rating:&lt;/strong&gt; The rating of the product.&lt;br&gt;
&lt;strong&gt;numReviews:&lt;/strong&gt; The number of reviews for the product.&lt;/p&gt;

&lt;p&gt;The Review interface represents a product review and includes the following properties:&lt;br&gt;
&lt;strong&gt;user:&lt;/strong&gt; The ID or username of the user who wrote the review.&lt;br&gt;
&lt;strong&gt;name:&lt;/strong&gt; The name of the reviewer.&lt;br&gt;
&lt;strong&gt;rating:&lt;/strong&gt; The rating given in the review.&lt;br&gt;
&lt;strong&gt;comment&lt;/strong&gt;: The text comment or review content.&lt;/p&gt;

&lt;p&gt;We defined a &lt;code&gt;ProductInDatabase&lt;/code&gt; Interface. This interface extends the Product interface and adds two additional properties:&lt;br&gt;
&lt;strong&gt;user:&lt;/strong&gt; The ID or username of the user associated with the product.&lt;br&gt;
&lt;strong&gt;reviews:&lt;/strong&gt; An array of product reviews. Each review conforms to the Review interface.&lt;/p&gt;

&lt;p&gt;We defined and exported &lt;code&gt;ProductDocument&lt;/code&gt; and &lt;code&gt;ProductModel&lt;/code&gt;Interfaces&lt;br&gt;
These interfaces are related to MongoDB and we are using them to define the structure of product documents in the database.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ProductDocument&lt;/code&gt; extends the ProductInDatabase interface and &lt;code&gt;Document&lt;/code&gt;. &lt;br&gt;
It represents a document in the database collection and includes all the properties defined in the ProductInDatabase interface.&lt;/p&gt;

&lt;p&gt;This interface also inherits functionality from &lt;code&gt;Document&lt;/code&gt; for interacting with our database.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ProductModel&lt;/code&gt; extends Model. It represents the model for interacting with the MongoDB collection. It is responsible for creating, querying, and modifying documents in the database collection.&lt;/p&gt;

&lt;p&gt;In the index.ts file in your types folder, add this to it to export the product types. &lt;br&gt;
&lt;code&gt;export * from "./product";&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing the Product model:
&lt;/h3&gt;

&lt;p&gt;Inside your models folder, create a file. Name it &lt;code&gt;productModel.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this code, we define Mongoose schemas and a model for our product. &lt;br&gt;
This represents a product in our database. &lt;br&gt;
We are using it to define the structure and behavior of the &lt;code&gt;"Product"&lt;/code&gt; document in our database.

&lt;p&gt;Firstly, we imported the necessary modules from Mongoose, including model and Schema.&lt;br&gt;
We also imported the &lt;code&gt;ProductDocument&lt;/code&gt; interface we defined earlier.&lt;/p&gt;

&lt;p&gt;We defined a &lt;code&gt;reviewSchema&lt;/code&gt;. This schema describes the structure of a product review with the following fields:&lt;br&gt;
** user:** A reference to the user who wrote the review. It's a MongoDB ObjectId and is required. The ref option specifies that it references the "User" model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;name:&lt;/strong&gt; The name of the reviewer, a required string.&lt;br&gt;
** rating*&lt;em&gt;: The rating given by the reviewer, a required number.&lt;br&gt;
**comment:&lt;/em&gt;* The review comment, a required string.&lt;/p&gt;

&lt;p&gt;The timestamps option is set to true, which automatically generates &lt;code&gt;createdAt&lt;/code&gt; and &lt;code&gt;updatedAt&lt;/code&gt; fields for each review.&lt;/p&gt;

&lt;p&gt;We define a &lt;code&gt;productSchema&lt;/code&gt;. It represents the structure of our product. It has the following fields:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;user:&lt;/strong&gt; A reference to the user who added the product&lt;br&gt;
**  name:** The name of the product, a required string.&lt;br&gt;
&lt;strong&gt;image:&lt;/strong&gt; The URL of the product's image, a required string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;brand:&lt;/strong&gt; The brand of the product, a required string.&lt;br&gt;
&lt;strong&gt;category:&lt;/strong&gt; The category of the product, a required string.&lt;br&gt;
&lt;strong&gt;description:&lt;/strong&gt; A description of the product, a required string.&lt;br&gt;
&lt;strong&gt;reviews:&lt;/strong&gt; An array of review documents. Each product can have multiple reviews, and we use the &lt;code&gt;reviewSchema&lt;/code&gt; to define their structure.&lt;br&gt;
&lt;strong&gt;rating:&lt;/strong&gt; The overall rating of the product, a number with a default value of 0.&lt;br&gt;
&lt;strong&gt;numReviews:&lt;/strong&gt; The number of reviews for the product, a number with a default value of 0.&lt;br&gt;
&lt;strong&gt;price:&lt;/strong&gt; The price of the product, a number with a default value of 0.&lt;br&gt;
&lt;strong&gt;countInStock:&lt;/strong&gt; The available quantity of the product, a number with a default value of 0.&lt;br&gt;
We also have the &lt;code&gt;timestamps&lt;/code&gt; set to true.&lt;/p&gt;

&lt;p&gt;Lastly, We created and eported a model named "Product". The model is associated with the &lt;code&gt;productSchema&lt;/code&gt;, and it's of type &lt;code&gt;ProductDocument&lt;/code&gt;. &lt;br&gt;
This model represents the product collection in our database and provides methods for interacting with our data.&lt;/p&gt;

&lt;p&gt;Inside the index.ts file in the models folder,update it with this code. &lt;br&gt;
&lt;code&gt;import { User } from "./userModel";&lt;br&gt;
import { Product } from "./productModel";&lt;br&gt;
export { User, Product };&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding the Product Controller:
&lt;/h3&gt;

&lt;p&gt;In the controller folder, create a file. Name it &lt;code&gt;productController.ts&lt;/code&gt; and add the following code to it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In this code, we have a function that fetches a list of products from our database.

&lt;p&gt;Firstly, we imported the &lt;code&gt;asyncHandler middleware&lt;/code&gt; from the &lt;code&gt;express-async-handler&lt;/code&gt; package. We will use this &lt;code&gt;middleware&lt;/code&gt; to handle asynchronous operations within our route handler.&lt;/p&gt;

&lt;p&gt;We imported the &lt;code&gt;Product&lt;/code&gt; model from the &lt;code&gt;models&lt;/code&gt; directory.&lt;br&gt;
We also imported the &lt;code&gt;Response&lt;/code&gt; and &lt;code&gt;Request&lt;/code&gt; types from the &lt;code&gt;types&lt;/code&gt;directory to ensure type safety in our route handler.&lt;/p&gt;

&lt;p&gt;We defined a route handler function named &lt;code&gt;getProducts&lt;/code&gt; to handle HTTP GET requests to the &lt;code&gt;/api/products&lt;/code&gt; endpoint.&lt;br&gt;
It takes &lt;code&gt;req&lt;/code&gt;(request) and &lt;code&gt;res&lt;/code&gt; (response) objects as parameters, representing the incoming request and the response to be sent.&lt;/p&gt;

&lt;p&gt;We set up pagination for the product list. We define a &lt;code&gt;pageSize&lt;/code&gt; of 10 products per page and retrieve the page number from the query parameter &lt;code&gt;pageNumber&lt;/code&gt;. If &lt;code&gt;pageNumber&lt;/code&gt; is not provided, it defaults to 1.&lt;br&gt;
Pagination allows clients to request specific pages of product results.&lt;/p&gt;

&lt;p&gt;We allow clients to search for products by specifying a search keyword in the query parameter keyword.&lt;/p&gt;

&lt;p&gt;If a keyword is provided, we create a keyword object to search for products with a partial case-insensitive match in the "name" field using regular expressions.&lt;br&gt;
If no keyword is provided, the keyword object is an empty object, meaning all products will be returned.&lt;/p&gt;

&lt;p&gt;To count our products in the database, We use Mongoose's &lt;code&gt;countDocuments&lt;/code&gt;method to count the total number of products that match the search criteria (including pagination).&lt;br&gt;
We are using this count to determine the total number of pages.&lt;/p&gt;

&lt;p&gt;To fetch all products from the database, we use the Mongoose's find method to retrieve the products. &lt;br&gt;
We apply the search criteria defined by the keyword object.&lt;/p&gt;

&lt;p&gt;We limit the number of products to &lt;code&gt;pageSize&lt;/code&gt; and skip the appropriate number of products based on the current page.&lt;br&gt;
The result is a list of products for the current page.&lt;/p&gt;

&lt;p&gt;In response, we send a JSON response to the client, including&lt;br&gt;
the list of products (products), current page number (page), total number of pages, calculated by dividing the total product count by the page size (pages).&lt;/p&gt;

&lt;p&gt;We exported the &lt;code&gt;getProducts&lt;/code&gt; route handler function so that it can be used in our application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding Product Routes:
&lt;/h3&gt;

&lt;p&gt;Inside your route folder, create a file. Name it &lt;code&gt;productRoutes.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we're setting up a route for handling requests to get all products from our database.

&lt;p&gt;We imported the &lt;code&gt;Express&lt;/code&gt; framework.&lt;br&gt;
 We also imported the &lt;code&gt;getProducts&lt;/code&gt; function from the &lt;code&gt;productController&lt;/code&gt; module. This function is responsible for fetching and sending a list of products in response to client requests.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const router = express.Router();&lt;/code&gt;: We create a new router instance using Express. &lt;br&gt;
&lt;code&gt;router.route("/").get(getProducts);&lt;/code&gt;: Here, we define a route for the root URL ("/"). &lt;br&gt;
When a GET request is made to the root URL, it will trigger the &lt;code&gt;getProducts&lt;/code&gt; function from the &lt;code&gt;productController&lt;/code&gt;. This function retrieves and sends a list of products as a response.&lt;/p&gt;

&lt;p&gt;Finally, we export the router instance so that it can be used in other parts of our application.&lt;/p&gt;

&lt;p&gt;Now let's make use of our product route in the &lt;code&gt;server.ts&lt;/code&gt; file.&lt;br&gt;
In this file, import the &lt;code&gt;productRoutes&lt;/code&gt; and use it like this:&lt;br&gt;
&lt;code&gt;import productRoutes from "./routes/productRoutes";&lt;br&gt;
// Use routes&lt;br&gt;
app.use("/api/products/", productRoutes);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;server.ts&lt;/code&gt; file should now look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Implementing orderTypes:
&lt;/h3&gt;

&lt;p&gt;Here we will be adding the types for the order. Inside your &lt;code&gt;types&lt;/code&gt; folder, create a file. Name it &lt;code&gt;order.ts&lt;/code&gt;and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we imported the Model and Document types from the Mongoose library. 

&lt;p&gt;We are using these types work with MongoDB models and documents.&lt;br&gt;
We also imported the &lt;code&gt;ProductDocument&lt;/code&gt; type. It represents the document structure of our product in the database.&lt;br&gt;
We defined some interfaces which represents different aspects of an order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OrderItems&lt;/strong&gt;: It describes the items within an order, including the name, quantity, image, price, and a reference to the associated product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ShippingAddress&lt;/strong&gt;: It represents the shipping address for a user, including fields for the address, city, postal code, and country.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PaymentResult&lt;/strong&gt;: It defines the result of a payment transaction, including an ID, status, update time, and email address.&lt;/p&gt;

&lt;p&gt;Order: It represents the overall order, combining information about the user who placed the order, the order items, shipping address, payment method, payment result, pricing details (items price, tax price, shipping price, total price), and flags to indicate whether the order is paid and delivered, along with timestamps.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export interface OrderDocument extends Order, Document {}:&lt;/code&gt; Here, we defined and interface called &lt;code&gt;OrderDocument&lt;/code&gt;. We are using this interface to extend the &lt;code&gt;Order&lt;/code&gt; interface and the&lt;code&gt;Document&lt;/code&gt; type from Mongoose and we also exported it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export interface OrderModel extends Model&amp;lt;OrderDocument&amp;gt; {}&lt;/code&gt;: Here, we also define an interface &lt;code&gt;OrderModel&lt;/code&gt;. This interface extends the Model type from Mongoose and is used to represent a model that interacts with the MongoDB database.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing order model:
&lt;/h3&gt;

&lt;p&gt;In the models folder, create a file. Name it &lt;code&gt;orderModel.ts&lt;/code&gt; and add the following code to it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we are defined the schema for an &lt;code&gt;Order&lt;/code&gt; document in the database. &lt;br&gt;
It represents an order made by a user in an our application.

&lt;p&gt;Firstly, we imported the necessary modules:&lt;br&gt;
 We imported the &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;Schema&lt;/code&gt; classes from the &lt;code&gt;mongoose&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;We also imported the &lt;code&gt;OrderDocument&lt;/code&gt; type.&lt;br&gt;
We then defined the an order schema called &lt;code&gt;orderSchema&lt;/code&gt; using the Schema class. &lt;br&gt;
The schema specifies the structure of the &lt;code&gt;Order&lt;/code&gt; document.&lt;br&gt;
The key fields we added to the schema are as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;user&lt;/strong&gt;: It's a reference to the user who placed the order. It's of type ObjectId and is required. The ref property indicates that it references the "User" model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;orderItems&lt;/strong&gt;: An array of objects, each representing an item in the order. Each item has fields like name, quantity (qty), image, price, and references the "Product" model for the product. These items are required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;shippingAddress&lt;/strong&gt;: An object containing address details, including address, city, postal code, and country. All these fields are required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;paymentMethod&lt;/strong&gt;: The payment method used for the order, which is a string and is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;paymentResult&lt;/strong&gt;: An object containing payment-related information, including an ID, status, update time, and email address. These fields are all optional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;itemsPrice, taxPrice, shippingPrice, and totalPrice&lt;/strong&gt;: These fields represent the pricing details of the order and are all numbers with default values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;isPaid and isDelivered&lt;/strong&gt;: These are Boolean fields representing whether the order has been paid and delivered, respectively. They are required with default values.&lt;/p&gt;

&lt;p&gt;**paidAt and deliveredAt: **These fields store timestamps indicating when the order was paid and delivered, respectively. They are of type Date.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing orderController:
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;controller&lt;/code&gt; create a folder. name it &lt;code&gt;orderController.ts&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we're implementing several functionalities related for managing our orders:&lt;/p&gt;

&lt;p&gt;We imported &lt;code&gt;asyncHandler&lt;/code&gt; from the "express-async-handler" package, which helps handle errors within asynchronous Express routes.&lt;/p&gt;

&lt;p&gt;We imported the &lt;code&gt;Order&lt;/code&gt; model from the "../models/" directory, allowing interaction with the "Order" collection in the database.&lt;/p&gt;

&lt;p&gt;We imported the Request and Response types from the "../types/express" file.&lt;br&gt;
We added the following route handlers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;addOrderItems:&lt;/strong&gt;&lt;br&gt;
This handles the creation of a new order by extracting the order items, shipping address, payment method, etc from the request body. &lt;/p&gt;

&lt;p&gt;It creates a new instance of the Order model with the extracted data and saves it to the database. &lt;br&gt;
If successful, it returns the created order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getOrderById:&lt;/strong&gt;&lt;br&gt;
 This retrieves a specific order by its ID from the database. If found, it returns the order details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;updateOrderToPaid:&lt;/strong&gt;&lt;br&gt;
 This updates an order's status to "paid" by modifying the isPaid field to true, setting the paidAt timestamp, and storing payment-related information. It then saves the updated order to the database.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;updateOrderToDelivered:&lt;/code&gt; Similar to the previous function, this updates an order's status to "delivered" by modifying the isDelivered field to true and setting the deliveredAt timestamp. It then saves the updated order to the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getMyOrders:&lt;/strong&gt;&lt;br&gt;
This retrieves all orders associated with the currently logged-in user by searching orders based on the user's ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getOrders:&lt;/strong&gt;&lt;br&gt;
This retrieves all orders from the database, populated with user information (ID and name).&lt;/p&gt;

&lt;p&gt;To be continue...adding the rest part of the article shortly.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Building SendCrypto: A Web 3.0 Application for Secure Blockchain Transactions</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Tue, 15 Aug 2023 14:06:16 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/building-sendcrypto-a-web-30-application-for-secure-blockchain-transactions-18ik</link>
      <guid>https://forem.com/jamesoyanna/building-sendcrypto-a-web-30-application-for-secure-blockchain-transactions-18ik</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;The rapid evolution of blockchain technology has paved the way for Web 3.0 and decentralized finance, a new era that is redefining the way we transact, invest, and interact with our money.&lt;/p&gt;

&lt;p&gt;This article delves into building &lt;strong&gt;SendCrypto&lt;/strong&gt;, a Web 3.0 application that enables users to perform transactions through the blockchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you will be building:
&lt;/h3&gt;

&lt;p&gt;You will be creating a fully-fledged Web 3.0 application that allows users to send transactions through the blockchain. &lt;/p&gt;

&lt;p&gt;Technologies you will be using for this project include React for the front-end, Hardhat-Ethers for Ethereum integration, and Solidity for the smart contract. &lt;/p&gt;

&lt;h3&gt;
  
  
  Application Demo:
&lt;/h3&gt;

&lt;p&gt;View the application Demo &lt;a href="https://send-crypto.netlify.app/"&gt;Here&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NNBqxSrB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uk490zh4hmngavm4ikit.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NNBqxSrB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uk490zh4hmngavm4ikit.PNG" alt="Send crypto" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bSbN6rkc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9upec2ueicdmhttisun.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bSbN6rkc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9upec2ueicdmhttisun.PNG" alt="Ethereum card" width="641" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you do not have a Meta mask setup on your browser, You can do that using this link - &lt;a href="https://support.metamask.io/hc/en-us/articles/360015489531-Getting-started-with-MetaMask"&gt;https://support.metamask.io/hc/en-us/articles/360015489531-Getting-started-with-MetaMask&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the link to the &lt;a href="https://github.com/jamesoyanna/send-crypto"&gt;github repository&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;The application allows users to make a transaction through the blockchain.&lt;/p&gt;

&lt;p&gt;-Each transaction is paired with an image and it is stored on the blockchain.&lt;/p&gt;

&lt;p&gt;When a user clicks on the connect to wallet button, it will immediately trigger a connection to the Metamask wallet, and it will request the account you want to connect to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connection to a meta mask account&lt;/strong&gt; - You will automatically see a display of the connected wallet address on the Ethereum card.&lt;/p&gt;

&lt;p&gt;You can switch your account to another account you want to send Ethereum to from the Metamask wallet.&lt;/p&gt;

&lt;p&gt;Input your wallet address on the transaction area. Specify the amount of Ethereum you want to send, add a keyword you would want to use and a message then click on the Send Now button&lt;/p&gt;

&lt;p&gt;Metamask automatically prompts a message describing the amount to be sent.&lt;/p&gt;

&lt;p&gt;-Click on confirm then a second notification will appear which is the contract interaction.&lt;/p&gt;

&lt;p&gt;Here, we are actually interacting with our Solidity smart contract doing this.&lt;/p&gt;

&lt;p&gt;If you scroll down, you will see the recent transactions being stored on the blockchain. Clicking on any transaction will take you to the Etherscan platform, where you will see the actual address and the real transaction.&lt;/p&gt;

&lt;p&gt;The focus of this tutorial will be to implement Web 3.0 into our React application, allowing it to send transactions through the blockchain and then store those transactions.&lt;/p&gt;

&lt;p&gt;We will be conducting our testing on the goerli faucet test network.&lt;/p&gt;

&lt;p&gt;Lets setup our development environment. &lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up the Development Environment:
&lt;/h3&gt;

&lt;p&gt;Now let's configure our development environment. We will start by setting up the frontend of the application using React. &lt;/p&gt;

&lt;p&gt;Before we begin, ensure you have Node.js and npm (Node Package Manager) installed on your machine. You can download them from the official Node.js website: &lt;a href="https://nodejs.org/"&gt;https://nodejs.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To verify if Node.js and npm are installed, open your terminal and run the following commands:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
node -v&lt;br&gt;
npm -v&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Create a New Project:
&lt;/h4&gt;

&lt;p&gt;create the main project folder, name it &lt;strong&gt;Sendcrypto&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will be using &lt;strong&gt;vite&lt;/strong&gt; to bootstrap our application. Vite is a build tool and development server for modern web development. It helps you set up a modern development environment with minimal configuration. &lt;/p&gt;

&lt;p&gt;To install Vite globally, run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm create vite@latest&lt;/code&gt;&lt;br&gt;
Then follow the instructions to install it.&lt;br&gt;
navigate into your project folder and run this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install&lt;br&gt;
npm run dev&lt;/code&gt;&lt;br&gt;
Ensure you you name the react application as client during installation.&lt;/p&gt;

&lt;p&gt;Your application should be running on  &lt;a href="http://127.0.0.1:5173/"&gt;http://127.0.0.1:5173/&lt;/a&gt; . Enter this address on your browser. If the installation is successful, you should see this on your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--blGOujMO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vyhsz0wjgxfh8z013u3u.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--blGOujMO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vyhsz0wjgxfh8z013u3u.PNG" alt="Vite landing page" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Installing tailwind CSS
&lt;/h4&gt;

&lt;p&gt;use these commands&lt;br&gt;
`npm install -D tailwindcss postcss autoprefixer&lt;/p&gt;

&lt;p&gt;npx tailwindcss init -p`&lt;/p&gt;

&lt;p&gt;Open your project with VScode editor&lt;/p&gt;

&lt;p&gt;copy the code below and paste on your tailwind.config file that was created when you ran the above command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;module.exports = { content: [ "./src/**/*.{js,jsx,ts,tsx}", ], theme: { extend: {}, }, plugins: [],}&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Add these code (directives) below to your index.css file&lt;/strong&gt;&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/tailwind"&gt;@tailwind&lt;/a&gt; base;&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/tailwind"&gt;@tailwind&lt;/a&gt; components;&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/tailwind"&gt;@tailwind&lt;/a&gt; utilities;&lt;/p&gt;

&lt;p&gt;You can now test your App by adding the code below in your &lt;code&gt;app.js&lt;/code&gt; file&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
to ensure your tailwind style is working.

&lt;p&gt;Now let's create the basic setup for our smart contract. Navigate into the smart_contract directory. and run the command:&lt;br&gt;
&lt;code&gt;npm init -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will initialize an empty &lt;code&gt;package.json&lt;/code&gt;. This would be the starting point of our smart contract.&lt;/p&gt;

&lt;p&gt;Now let's create our react application that will display our transactions on the frontend.&lt;/p&gt;

&lt;p&gt;Navigate to your &lt;code&gt;client&lt;/code&gt; folder of your react application. Add a folder in the &lt;code&gt;src&lt;/code&gt; directory. Name it components.&lt;/p&gt;

&lt;p&gt;We can start adding our components. Inside the components folder, add the following files &lt;code&gt;Navbar.jsx&lt;/code&gt; &lt;code&gt;Footer.jsx&lt;/code&gt;, &lt;code&gt;Services.jsx&lt;/code&gt;, &lt;code&gt;Loader.jsx&lt;/code&gt; &lt;code&gt;Transactions.jsx&lt;/code&gt; &lt;code&gt;Welcome.jsx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To allow us to export all these components from a single file, add a file in the components folder. Name it &lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Export all the components you have created in the index.js file. It should now look like this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Add the following basic contents to the components you have created.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now update your &lt;code&gt;App.jsx&lt;/code&gt; by importing these components into them. &lt;br&gt;
Your &lt;code&gt;App.jsx&lt;/code&gt; should now look like this.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;If everything works fine you should now see this on your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gxNVROoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvsj08862rga2di4dwpo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gxNVROoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvsj08862rga2di4dwpo.PNG" alt="Initial page" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding style to our App:&lt;/strong&gt;&lt;br&gt;
To add style to our application simply copy the style below and add it to your index.css file. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For the icons we will use throughout the project, install the react icons using this command:&lt;br&gt;
&lt;code&gt;npm i react-icons&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For the logo, create a folder inside the &lt;code&gt;src&lt;/code&gt; folder and add add a logo image of your choice to it.&lt;/p&gt;

&lt;p&gt;Now let's add the code for the Navbar component:&lt;br&gt;
Open the &lt;code&gt;Navbar.jsx&lt;/code&gt; file and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we imported the required modules and resources. We imported React from the "react" package, icons like HiMenuAlt4 from the &lt;code&gt;react-icons/hi&lt;/code&gt; package, and &lt;code&gt;AiOutlineClose&lt;/code&gt; from the &lt;code&gt;react-icons/ai&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;We then added a logo image by importing it from the "../images/logo.png" file&lt;/p&gt;

&lt;p&gt;We also define a functional component &lt;code&gt;NavBarItem&lt;/code&gt;. It takes two props, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;classprops&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Inside the component, it returns a list element with the title as its content and applies CSS classes for margin, cursor, and any additional classes provided via &lt;code&gt;classprops&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside our Navbar component,we sets up a state variable &lt;code&gt;toggleMenu&lt;/code&gt; and a state updater function &lt;code&gt;setToggleMenu&lt;/code&gt; using the &lt;code&gt;useState&lt;/code&gt; hook. The initial state of &lt;code&gt;toggleMenu&lt;/code&gt; is false.&lt;/p&gt;

&lt;p&gt;In our &lt;code&gt;jsx&lt;/code&gt; we, render a responsive navigation bar component that includes a logo, navigation items, and a mobile menu toggle.&lt;/p&gt;

&lt;p&gt;It adapts to both desktop and mobile screen sizes, providing easy navigation through a list of items and a mobile menu toggle.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;Navbar&lt;/code&gt; should now look like this on the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qwL2LVBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ghcbgh8gcayf0u8sabi.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qwL2LVBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ghcbgh8gcayf0u8sabi.PNG" alt="Navbar" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's add the code for the &lt;code&gt;Welcome&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;Welcome.jsx&lt;/code&gt; file and add the code below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this &lt;code&gt;Welcome&lt;/code&gt; component, we updated it by first we import of several icons from the "react-icons" library.&lt;/p&gt;

&lt;p&gt;We define a constant &lt;code&gt;companyCommonStyles&lt;/code&gt;.This contains a set of CSS classes.&lt;/p&gt;

&lt;p&gt;We also define a functional component called &lt;code&gt;Input&lt;/code&gt;. It takes props like &lt;code&gt;placeholder, name, type, value, and handleChange&lt;/code&gt;, and renders an input element with various properties and styling.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;Welcome&lt;/code&gt; component, we declared three functions -  &lt;code&gt;connectWallet&lt;/code&gt; and &lt;code&gt;handleSubmit&lt;/code&gt; and an empty &lt;code&gt;handleChange&lt;/code&gt;function. We will add the logic for these functions later&lt;/p&gt;

&lt;p&gt;The return statement of the Welcome component starts by rendering a structure of HTML elements.&lt;br&gt;
The content section includes headings, a description, and a "Connect Wallet" button.&lt;/p&gt;

&lt;p&gt;We added a section that includes a grid of information boxes with text like "Reliability", "Security", "Ethereum", etc. These boxes represent features of the platform.&lt;/p&gt;

&lt;p&gt;We also added a button to send crypto.&lt;/p&gt;

&lt;p&gt;Your application should now look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UC9cndGz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9cl5v7w905ymptyt2h0g.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UC9cndGz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9cl5v7w905ymptyt2h0g.PNG" alt="Welcome page" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding the Service Component:
&lt;/h3&gt;

&lt;p&gt;Now inside your client folder, open the Services.jsx file and the following code :&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we imported several icons from the &lt;code&gt;react-icons&lt;/code&gt;package.&lt;/p&gt;

&lt;p&gt;We then define a functional component &lt;code&gt;ServiceCard&lt;/code&gt; that takes several props: color, title, icon, and subtitle.&lt;/p&gt;

&lt;p&gt;This component represents a card-like structure containing service details.&lt;br&gt;
We use the color prop to determine the background color of the circular icon container.&lt;/p&gt;

&lt;p&gt;The icon prop is a React element representing the icon for the service.&lt;br&gt;
The title prop is the title of the service.&lt;br&gt;
The subtitle prop is the description of the service.&lt;br&gt;
The card structure is built using flexbox classes for layout and styling.&lt;/p&gt;

&lt;p&gt;We also define another functional component &lt;code&gt;Services&lt;/code&gt;.&lt;br&gt;
This component wraps the content of the services section, providing a gradient background.&lt;/p&gt;

&lt;p&gt;Inside the component, we added a nested div element with various styling classes applied to control layout and spacing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding Footer Component:
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;Footer.jsx&lt;/code&gt; file we previously created, add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code above, we define a React functional component called Footer, which serves as a footer section for our application. &lt;/p&gt;

&lt;p&gt;The footer contains various elements such as a logo, navigation links, contact information, and copyright text. &lt;/p&gt;

&lt;p&gt;We also imported the image named &lt;code&gt;logo.png&lt;/code&gt; from the ../images/ directory to be used for our logo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Helper functions:
&lt;/h3&gt;

&lt;p&gt;We will be adding some helper functions and reusable code snippets that we will be using throughout the application.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src&lt;/code&gt; folder, create a folder and name it &lt;code&gt;utils&lt;/code&gt;. create a file inside the &lt;code&gt;utils&lt;/code&gt; folder, name it &lt;code&gt;Transactions.json&lt;/code&gt;, and add the following code to it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, is a JSON object that describes an &lt;code&gt;Ethereum&lt;/code&gt;smart contract called "Transactions" written in Solidity. &lt;/p&gt;

&lt;p&gt;It includes information about the contract's name, source file path, ABI (interface for external interaction), compiled bytecode, and deployed bytecode. &lt;/p&gt;

&lt;p&gt;The ABI outlines the contract's functions and events, while the bytecode is the low-level code that runs on the Ethereum network.&lt;/p&gt;

&lt;p&gt;This artifact is essential for deploying, interacting with, and understanding our contract programmatically.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;utils&lt;/code&gt; folder, create another file. Name it &lt;code&gt;constants.js&lt;/code&gt; and add the following code to it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code above, we imported the &lt;code&gt;ABI(interface for external interaction)&lt;/code&gt; of the smart contract from the &lt;code&gt;Transactions.json&lt;/code&gt; file we created.&lt;br&gt;
We declared a constant variable named &lt;code&gt;contractAddress&lt;/code&gt;, which contains the &lt;code&gt;Ethereum&lt;/code&gt; address where the smart contract has been deployed. This address is represented as a hexadecimal string.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
export const contractABI = abi.abi;&lt;/code&gt;&lt;br&gt;
In this line of code, we declared a constant variable named &lt;code&gt;contractABI&lt;/code&gt;. It assigns the abi property of the imported abi object to contractABI. &lt;/p&gt;

&lt;p&gt;This &lt;code&gt;contractABI&lt;/code&gt; represents the ABI of the smart contract and will be used in various parts of the application to interact with the contract's functions and events.&lt;/p&gt;

&lt;p&gt;What we have done in this whole code module is to provide a central location for storing the contract's address and ABI, so as to make it easy for us to access and use these details throughout the application.&lt;/p&gt;

&lt;p&gt;Inside the utils file, add create another file. Name it &lt;code&gt;shortenAddress.js&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code above, we define a function called &lt;code&gt;shortenAddress&lt;/code&gt;. It takes in an Ethereum address as input and returns a shortened version of that address.&lt;/p&gt;

&lt;p&gt;Ethereum addresses are typically long hexadecimal strings, and this function is intended to make them more visually manageable.&lt;/p&gt;

&lt;p&gt;So, when you call the &lt;code&gt;shortenAddress&lt;/code&gt; function with a full Ethereum address as an argument, it will return a string that shows the first five characters, an ellipsis, and the last four characters of the address.&lt;/p&gt;

&lt;p&gt;Let's also add dummy transaction data that would serve as default transactions on the blockchain.&lt;br&gt;
Inside the utils folder create a file. Name it &lt;code&gt;dummyData.js&lt;/code&gt; and add the following code to it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code above, we exported an array of objects, each representing a transaction with certain details. 

&lt;p&gt;Each object in the array contains information about the sender's address, receiver's address, amount, timestamp, and a GIF URL. &lt;br&gt;
This represent a series of transactions in our blockchain application.&lt;/p&gt;

&lt;p&gt;Now next we will use the React Context API to manage and share the state and functions relating to Ethereum transactions across our components without the need to pass props explicitly through component nesting.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src&lt;/code&gt; folder, create a folder. name it context. Inside the context folder, create a file. Name it &lt;code&gt;TransactionContext.jsx&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code above, we define a React context provider called &lt;code&gt;TransactionsProvider&lt;/code&gt; that manages interactions with our blockchain contract using the Ethereum blockchain and MetaMask.&lt;/p&gt;

&lt;p&gt;Firstly, we imported necessary libraries and modules, including React, useEffect, useState for managing component state, and the ethers library for interacting with the Ethereum blockchain.&lt;/p&gt;

&lt;p&gt;We also imported &lt;code&gt;contractABI&lt;/code&gt; and &lt;code&gt;contractAddress&lt;/code&gt; from the &lt;code&gt;constant&lt;/code&gt; module we defined earlier. &lt;/p&gt;

&lt;p&gt;We created a context named &lt;code&gt;TransactionContext&lt;/code&gt; using React.createContext(). This context will provide the necessary data and functions related to transactions to its consumers.&lt;/p&gt;

&lt;p&gt;We define a &lt;code&gt;createEthereumContract&lt;/code&gt; function. This initializes the Ethereum contract using the &lt;code&gt;contractAddress&lt;/code&gt; and &lt;code&gt;contractABI&lt;/code&gt;. It uses the &lt;code&gt;MetaMask&lt;/code&gt; provider to obtain a signer and interact with the contract.&lt;/p&gt;

&lt;p&gt;We define several state variables:&lt;br&gt;
&lt;code&gt;formData:&lt;/code&gt; Tracks form data such as the recipient's address, amount, keyword, and message.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;currentAccount:&lt;/code&gt; Stores the current Ethereum account's address.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;isLoading:&lt;/code&gt; Indicates whether a transaction is currently being processed.&lt;br&gt;
&lt;code&gt;transactionCount&lt;/code&gt;: Stores the number of transactions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;transactions:&lt;/code&gt; Holds an array of structured transaction objects.&lt;/p&gt;

&lt;p&gt;For our Data Fetching and Processing, we defined several functions:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
getAllTransactions:&lt;/code&gt; Uses the contract instance to fetch all transactions from the blockchain, processes the data, and updates the transactions state.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;checkIfWalletIsConnect:&lt;/code&gt; Checks if &lt;code&gt;MetaMask&lt;/code&gt; is installed, gets the user's Ethereum accounts, and updates the &lt;code&gt;currentAccount&lt;/code&gt;state. It then calls &lt;code&gt;getAllTransactions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;checkIfTransactionsExists:&lt;/code&gt; Initializes the &lt;code&gt;transactionCount&lt;/code&gt; using the contract's method to get the count of transactions.&lt;/p&gt;

&lt;p&gt;Wallet Connection and Transaction Submission:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;connectWallet:&lt;/code&gt; This function requests user account access from &lt;code&gt;MetaMask&lt;/code&gt; and updates the &lt;code&gt;currentAcc&lt;/code&gt;ount`.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sendT&lt;/code&gt;ransaction:&lt;code&gt; Constructs and sends an &lt;/code&gt;Ethereum` transaction using MetaMask. &lt;/p&gt;

&lt;p&gt;It also interacts with the smart contract to add the transaction to the blockchain. It updates the &lt;code&gt;transactionCount&lt;/code&gt; after the transaction is successful.&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;useEffect&lt;/code&gt; hook is used to automatically check for wallet connection and existing transactions when the &lt;code&gt;transactionCount&lt;/code&gt; changes. This helps keep the UI in sync with the blockchain.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;TransactionsProvider&lt;/code&gt; component wraps its children in the &lt;code&gt;TransactionContext.Provider&lt;/code&gt;. It exposes various state variables and functions related to transactions to its children.&lt;/p&gt;

&lt;p&gt;Since we are using the &lt;code&gt;ethers&lt;/code&gt; library, you will need to install it for our application to work properly.&lt;br&gt;
Navigate to your client directory, open your command-line and run this command to install &lt;code&gt;ethers&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i ethers&lt;/code&gt;&lt;br&gt;
To start your server again by running the command: &lt;code&gt;npm run dev&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;We will also wrap our application with a custom context provider. This will provide the context data and functions related to &lt;code&gt;Ethereum&lt;/code&gt; transactions to all components rendered within it.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;main.jsx&lt;/code&gt; file with the following code:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we added the &lt;code&gt;TransactionsProvider&lt;/code&gt; by importing it from the &lt;code&gt;TransactionContext&lt;/code&gt; in the context folder.

&lt;p&gt;The &lt;code&gt;TransactionsProvider&lt;/code&gt; is a custom context provider that wraps our main &lt;code&gt;App&lt;/code&gt; component. It provides the context data and functions for &lt;code&gt;Ethereum&lt;/code&gt; transactions.&lt;/p&gt;

&lt;p&gt;We want to add a custom hook to fetch GIFs images from the &lt;code&gt;Giphy API&lt;/code&gt;. &lt;br&gt;
Inside your &lt;code&gt;src&lt;/code&gt; folder, create a new folder, name it &lt;code&gt;hooks&lt;/code&gt;. Inside the hooks folder add a file. Name it &lt;code&gt;useFetch.jsx&lt;/code&gt; and add the following code:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we define a custom React hook named &lt;code&gt;useFetch&lt;/code&gt; that is used to fetch &lt;code&gt;GIFs&lt;/code&gt; from the &lt;code&gt;Giphy API&lt;/code&gt; based on a provided keyword. &lt;/p&gt;

&lt;p&gt;It uses the &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; hooks to manage the state and handle the asynchronous fetching of &lt;code&gt;GIFs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we will be adding our &lt;code&gt;transactions&lt;/code&gt;component logic. Inside the Transactions.jsx file in the components folder, add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we define two components: &lt;code&gt;TransactionsCard&lt;/code&gt; and &lt;code&gt;Transactions&lt;/code&gt;. We use these components to display a list of transactions with associated information, including &lt;code&gt;GIFs&lt;/code&gt; fetched based on keywords.&lt;/p&gt;

&lt;p&gt;We imported the &lt;code&gt;useContext&lt;/code&gt; from the "react" library. The TransactionContext is imported from "../context/TransactionContext".&lt;/p&gt;

&lt;p&gt;We imported the &lt;code&gt;useFetch&lt;/code&gt; custom hook from "../hooks/useFetch".&lt;/p&gt;

&lt;p&gt;We also imported the &lt;code&gt;dummyData&lt;/code&gt; and &lt;code&gt;shortenAddress&lt;/code&gt; functions from their respective paths.&lt;/p&gt;

&lt;p&gt;We define &lt;code&gt;TransactionsCard&lt;/code&gt; functional component which takes various props (addressTo, addressFrom, timestamp, message, keyword, amount, url) to render a transaction card.&lt;/p&gt;

&lt;p&gt;We use the &lt;code&gt;useFetch&lt;/code&gt; hook to fetch GIFs based on the keyword prop.&lt;/p&gt;

&lt;p&gt;We define the &lt;code&gt;Transactions&lt;/code&gt; functional component which displays a list of transaction cards using the &lt;code&gt;TransactionsCard&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;It uses the &lt;code&gt;useContext&lt;/code&gt; hook to access the transactions array and &lt;code&gt;currentAccount&lt;/code&gt; from the &lt;code&gt;TransactionContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Depending on whether there is a &lt;code&gt;currentAccount&lt;/code&gt;, it displays a message suggesting to connect an account or showing the "Latest Transactions" header.&lt;/p&gt;

&lt;p&gt;The list of transactions is rendered using the map function, combining the &lt;code&gt;dummyData&lt;/code&gt; (predefined transactions) and the dynamic transactions from context.&lt;/p&gt;

&lt;p&gt;Now let's update our &lt;code&gt;Welcome&lt;/code&gt; component to add the logic for &lt;code&gt;connectWallet&lt;/code&gt;, &lt;code&gt;handleSubmit&lt;/code&gt; and &lt;code&gt;handleChange&lt;/code&gt; functions we had earlier defined.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;Welcome.jsx&lt;/code&gt;file in the components folder, update it with the following code:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code above we updated the &lt;code&gt;handleSubmit&lt;/code&gt; function in our previous code by using destructuring to extract values from the &lt;code&gt;formData&lt;/code&gt; object. &lt;/p&gt;

&lt;p&gt;The formData object holds data the users inputed in the form.&lt;/p&gt;

&lt;p&gt;The values we extracted are addressTo, amount, keyword, and message, which represent the recipient's address, transaction amount, GIF keyword, and message respectively.&lt;/p&gt;

&lt;p&gt;We prevented the default behavior of the form submission event by using &lt;code&gt;e.preventDefault();&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (!addressTo || !amount || !keyword || !message) return;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a conditional statement that checks whether any of the extracted values (i.e., addressTo, amount, keyword, message) are falsy. &lt;/p&gt;

&lt;p&gt;If any of these values are falsy (empty or not provided), the condition evaluates to true, and the code inside the if-block doesn't run. This effectively stops the function from continuing if any required field is missing.&lt;/p&gt;

&lt;p&gt;If all the required fields (addressTo, amount, keyword, message) have valid values, the &lt;code&gt;sendTransaction&lt;/code&gt; function is invoked.&lt;/p&gt;

&lt;p&gt;This function initiates the process of sending a cryptocurrency transaction based on the user's input data.&lt;/p&gt;

&lt;p&gt;We will also add the code for the &lt;code&gt;Loader&lt;/code&gt; component. Inside the &lt;code&gt;Loader.jsx&lt;/code&gt; file we have created earlier, add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we define an arrow function component named &lt;code&gt;Loader&lt;/code&gt;. This is a simple circular loading animation.

&lt;p&gt;When this component is rendered in our application, it will display a spinning circle with a red border at the bottom. It's often used to show that some asynchronous operation (like data fetching) is in progress.&lt;/p&gt;
&lt;h3&gt;
  
  
  Connecting application to the blockchain
&lt;/h3&gt;

&lt;p&gt;Now let's connect our application to the blockchain. We will be writing a solidity contract that keeps track of all the transactions that went through the blockchain.&lt;/p&gt;

&lt;p&gt;Let's add the dependencies for our smart contract. &lt;br&gt;
Switch to your &lt;code&gt;smart_contract&lt;/code&gt; folder and from your project in your command-line, run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i hardhat @nomiclabs/hardhat-waffle @nomiclabs/hardhat-ethers chai ethereum-waffle ethers&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hardhat is an Ethereum development environment. It enables us to easily deploy contracts, run tests, and debug Solidity code without dealing with live environments. You can read more on their documentation &lt;a href="https://hardhat.org/hardhat-runner/docs/getting-started"&gt;Hardhat Doc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the dependencies have finished installing, run the command:&lt;br&gt;
&lt;code&gt;npx hardhat&lt;/code&gt; and follow the instructions. Press yes to accept the questions. New files and folders are added to your project directory. You can run an initial test by running the command &lt;br&gt;
&lt;code&gt;npx hardhat test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also, ensure you install the solidity extension on your Vscode. This would make your writing of solidity code easier.&lt;/p&gt;

&lt;p&gt;here is it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m14Lw8XG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t538r7y3fzyphqq7wlh9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m14Lw8XG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t538r7y3fzyphqq7wlh9.PNG" alt="Solidity Extension" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's write our smart contract for our transactions.&lt;br&gt;
Inside the &lt;code&gt;contracts&lt;/code&gt; folder in your &lt;code&gt;smart_contract&lt;/code&gt; directory, add a file called &lt;code&gt;Transactions.sol&lt;/code&gt;. Inside it add the following code below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we use the &lt;code&gt;pragma&lt;/code&gt; directive that specifies the version of the Solidity compiler that should be used. &lt;/p&gt;

&lt;p&gt;The caret (^) symbol means the code is compatible with compiler versions greater than or equal to 0.8.0. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;contract Transactions {&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
Then, we define a Solidity smart contract named &lt;code&gt;Transactions&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;uint256 transactionCount;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we declare a state variable &lt;code&gt;transactionCount&lt;/code&gt; of type uint256, which will be used to keep track of the number of transactions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;event Transfer(address from, address receiver, uint amount, string message, uint256 timestamp, string keyword);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we define an event named &lt;code&gt;Transfer&lt;/code&gt;. Events are simply a way for contracts to communicate that something has happened. &lt;/p&gt;

&lt;p&gt;This event is used to log transaction details, such as sender, receiver, amount, message, timestamp, and keyword.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
struct TransferStruct {&lt;br&gt;
    address sender;&lt;br&gt;
    address receiver;&lt;br&gt;
    uint amount;&lt;br&gt;
    string message;&lt;br&gt;
    uint256 timestamp;&lt;br&gt;
    string keyword;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we define a structure named &lt;code&gt;TransferStruct&lt;/code&gt; which holds the components of a transaction. It includes the sender's and receiver's addresses, the transaction amount, a message, timestamp, and a keyword associated with the transaction&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TransferStruct[] transactions;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We then declare a dynamic array named transactions that will store instances of &lt;code&gt;TransferStruct&lt;/code&gt;, representing the recorded transactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function addToBlockchain(address payable receiver, uint amount, string memory message, string memory keyword) public {
    transactionCount += 1;
    transactions.push(TransferStruct(msg.sender, receiver, amount, message, block.timestamp, keyword));

    emit Transfer(msg.sender, receiver, amount, message, block.timestamp, keyword);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we added an &lt;code&gt;addToBlockchain&lt;/code&gt; function. This would allow a user to add a new transaction to the blockchain. &lt;/p&gt;

&lt;p&gt;What it simply does is it increments the &lt;code&gt;transactionCount&lt;/code&gt;, creates a new instance of &lt;code&gt;TransferStruct&lt;/code&gt; with the provided parameters, pushes it to the transactions array, and emits the Transfer event to log the transaction details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function getAllTransactions() public view returns (TransferStruct[] memory) {
    return transactions;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we define a function, &lt;code&gt;getAllTransactions&lt;/code&gt;, which is a view function that returns the entire array of recorded transactions when called. It doesn't modify the contract's state.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function getTransactionCount() public view returns (uint256) {&lt;br&gt;
    return transactionCount;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And lastly, we define a function, &lt;code&gt;getTransactionCount&lt;/code&gt;, which is also a view function that returns the current value of &lt;code&gt;transactionCount.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;From deploy - When we run the deploy code, we are going to get the address of our smart contract deployed on the blockchain network&lt;/p&gt;

&lt;p&gt;For our contract to be deployed, we need to have Ethereum on our own wallet already because everything on the blockchain network requires what we know as gas.&lt;/p&gt;

&lt;p&gt;To get a wallet account signup for the Metamask account and use it on your browser as an extension.&lt;/p&gt;

&lt;p&gt;Metamask is an extension to accessing Ethereum-enabled distributed applications or Dapps in your browser. You can install it here - &lt;a href="https://metamask.io/download/"&gt;https://metamask.io/download/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To deploy our smart contract, we will be using Alchemy. Its a platform that would enable us deploy our smart contract. You can signup for an account &lt;a href="https://www.alchemy.com/"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get a free Ethereum to test our contract, you can get from the ropsen test network or from goerli faucet - &lt;a href="https://goerlifaucet.com/"&gt;https://goerlifaucet.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you have created Alchemy account, it should take you to the dashboard like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jdRwsG2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpm4665xx1dazx8erj03.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jdRwsG2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpm4665xx1dazx8erj03.PNG" alt="Alchemy dashboard" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Apps Menus on the Dashboard and click on the create App button to create an App. See below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--URmSZ5kw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyga05gyvqv313nqpv8x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--URmSZ5kw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyga05gyvqv313nqpv8x.PNG" alt="Create App" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing code to deploy your application.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>react</category>
      <category>ethers</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Developing A Task Management ChatGPT Plugin with Typescript</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Thu, 10 Aug 2023 13:53:08 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/developing-a-task-management-chatgpt-plugin-with-typescript-a5m</link>
      <guid>https://forem.com/jamesoyanna/developing-a-task-management-chatgpt-plugin-with-typescript-a5m</guid>
      <description>&lt;p&gt;Task management is an essential aspect of productivity and organization in both personal and professional settings. &lt;/p&gt;

&lt;p&gt;With the rise of virtual assistants and chatbots, integrating task management capabilities into these platforms has become increasingly popular. &lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a ChatGPT plugin using Next.js, leveraging its new functionality and routes. The goal of our plugin is to provide task management capabilities, allowing users to list, create, and delete tasks. &lt;/p&gt;

&lt;p&gt;Additionally, we will enable querying information about tasks, such as the number of remaining tasks. By the end of this tutorial, you will have a solid understanding of how to develop your own custom plugins.&lt;/p&gt;

&lt;p&gt;To keep things simple, we will store our task data in memory using a store-like structure. However, in a production application, you would typically use a database for persistent storage. Now, let's dive into the development process.&lt;/p&gt;

&lt;p&gt;To start with, we will scaffold our application by running : &lt;code&gt;npx create-next-app chat-gpt-plugin&lt;/code&gt;&lt;br&gt;
Following the prompt and select the appropriate instruction guide like this. choose&lt;/p&gt;

&lt;p&gt;Would you like to use TypeScript with this project? ...Yes&lt;br&gt;
Would you like to use ESLint with this project? » Yes&lt;br&gt;
Would you like to use Tailwind CSS with this project? » No&lt;br&gt;
Would you like to use &lt;code&gt;src/&lt;/code&gt; directory with this project? » Yes&lt;br&gt;
Use App Router (recommended)? » Yes&lt;br&gt;
Would you like to customize the default import alias? » Yes&lt;br&gt;
 What import alias would you like configured? ... @/* - press enter&lt;/p&gt;

&lt;p&gt;Following these steps would create our nextjs application. &lt;/p&gt;

&lt;p&gt;Now, to start our application, navigate into the newly created &lt;code&gt;chat-gpt-plugin&lt;/code&gt; folder and run :&lt;br&gt;
&lt;code&gt;npm run dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your application should now be running on &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;. Go to your browser and visit this address.&lt;/p&gt;

&lt;p&gt;If everything works fine, you should see this Nextjs page in your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F923owkfluurg631wj3h1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F923owkfluurg631wj3h1.PNG" alt="Frontpage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's open the ChatGPT documentation on the OpenAI website and explore the relevant section for our plugin. This documentation will serve as our reference throughout the development process.&lt;/p&gt;

&lt;p&gt;Once you have reviewed the documentation, let's return to our application. We need to set up some configurations, starting with the headers to enable Cross-Origin Resource Sharing (CORS) for the ChatGPT API at &lt;a href="https://platform.openai.com/docs/plugins/getting-started" rel="noopener noreferrer"&gt;Open API Doc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside our &lt;code&gt;nextconfig&lt;/code&gt; file, in your project folder, add the following code:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Here in this code, we provided a configuration for our application.

&lt;p&gt;The headers function here is an asynchronous function that we set up as custom headers for specific routes. &lt;/p&gt;

&lt;p&gt;We set the Access-Control-Allow-Origin header to allow requests from &lt;a href="https://chat.openai.com" rel="noopener noreferrer"&gt;https://chat.openai.com&lt;/a&gt; for all routes matching the /:path* pattern. &lt;/p&gt;

&lt;p&gt;This is necessary in order to register our plugin.&lt;/p&gt;

&lt;p&gt;Now, inside the public folder create a folder called &lt;code&gt;.well-know&lt;/code&gt;. Create a file inside the .well-know directory called &lt;code&gt;ai-plugin.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ai-plugin.json&lt;/code&gt; is a manifest that provides information about your plugin, such as its name, version, and main configuration endpoint, which can be used by the ChatGPT system to interact with your plugin effectively.&lt;/p&gt;

&lt;p&gt;Add the following code to the &lt;code&gt;ai-plugin.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code we simply provide a JSON object that represents the schema of our Chatgpt plugin.&lt;/p&gt;

&lt;p&gt;This JSON object follows the schema defined for chatgpt plugins and provides essential information about the plugin, including its name, description, authentication requirements, API details, logo, contact email, and legal information.&lt;/p&gt;

&lt;p&gt;Now let's create the main configuration for our app.&lt;/p&gt;

&lt;p&gt;In the  public directory, create a file. Name it &lt;code&gt;openapi.yml&lt;/code&gt; and add the following code to it :&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code,  we added a specification for defining and documenting the APIs&lt;br&gt;
&lt;code&gt;openapi: 3.0.1:&lt;/code&gt; Here we specify that the API is using the OpenAPI version 3.0.1.&lt;/p&gt;

&lt;p&gt;We then provided information about the API, including its title, description, and version&lt;/p&gt;

&lt;p&gt;&lt;code&gt;servers:&lt;/code&gt; We define the server where the API is hosted. In this case, the server is specified as &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;paths:&lt;/code&gt; This is the heart of the API specification. It defines the various paths (URL endpoints) that the API exposes, along with the HTTP methods (such as GET, POST, etc.) that can be used on those paths.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/api/tasks:&lt;/code&gt; This is a path for getting the list of tasks. It uses the HTTP GET method. &lt;br&gt;
The responses section specifies the possible responses from the API, including the HTTP status code and a description.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
/api/create-task:&lt;/code&gt; This path is for adding a new task. It uses the HTTP POST method. The request body section specifies that the request must include a JSON body with a task property. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/api/delete-task:&lt;/code&gt; This path is for deleting a task. It also uses the HTTP POST method.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
schemas:&lt;/code&gt;This subsection defines the data structures used in the API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deleteTaskRequest:&lt;/code&gt; This schema defines the structure of the request body required for deleting a task. It contains a single property task of type string.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;addTaskRequest:&lt;/code&gt; This schema defines the structure of the request body required for adding a new task. It also contains a single property task of type string.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getTasksResponse:&lt;/code&gt; This schema defines the structure of the response body when getting the list of tasks. It includes a property &lt;code&gt;tasks&lt;/code&gt; which is an array of strings.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Building Scalable Fintech Applications: A Practical Guide for African Entrepreneurs</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Mon, 19 Jun 2023 17:18:44 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/building-scalable-fintech-applications-a-practical-guide-for-african-entrepreneurs-2e1b</link>
      <guid>https://forem.com/jamesoyanna/building-scalable-fintech-applications-a-practical-guide-for-african-entrepreneurs-2e1b</guid>
      <description>&lt;p&gt;Africa and Nigeria in particular are clearly in the midst of one of the most exciting phases of innovation and disruption in the financial sector.&lt;/p&gt;

&lt;p&gt;Today, Fintech is emerging as a tech enabler in Nigeria,improving financial inclusion and serving as a catalyst for innovation in other sectors, such as agriculture and healthcare.&lt;/p&gt;

&lt;p&gt;The increasing need for mobile money transfers and the underserving of small and medium enterprises in rural communities has created an opening that fintech startups have been quick to take advantage of.&lt;/p&gt;

&lt;p&gt;No doubt, fintech startups are challenging traditional banking structures and are creating efficiency gains by opening up the financial services value chain.&lt;/p&gt;

&lt;p&gt;This rise of fintech startups has put the demand for custom fintech applications on the rise as well. However, building a financial technology app is some real work.&lt;/p&gt;

&lt;p&gt;I have had entrepreneurs who have discussed with me developing on fintech applications but are yet to do the groundwork in the early development phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Below, I have highlighted these points that can serve as a practical guide to building a scalable fintech application.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose a specific area:
&lt;/h3&gt;

&lt;p&gt;When you have come up with an idea for your proposed fintech solution, you need to find a particular area or niche you want to develop the application for. A niche constitutes a set of areas a fintech startup could focus on for example;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specific Demographics&lt;/strong&gt;: You could target specific portions of the populace, like young adults or pensioners. Specific Industry: You could also target specific industries, such as offering loans, insurance, and payments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get your legal framework right:
&lt;/h3&gt;

&lt;p&gt;There are several regulations put in place by the central bank for the operation of a financial service application. These regulations are very important because financial services are highly regulated.&lt;/p&gt;

&lt;p&gt;Knowing the standards and regulations put in place by the Apex bank is crucial to developing a successful fintech product. Discovering new laws and rules while you’re already deep into the development process might cause major changes in the app’s features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know the exact problem you are solving:
&lt;/h3&gt;

&lt;p&gt;You need to ask these questions. What problem are you addressing with the app?. What unique solution the application is providing for users? And what features should it include? You need to have a clear vision of the final result you are trying to build.&lt;/p&gt;

&lt;p&gt;When you have made good market research, your team will come up with a final idea of a business case that will be competitive and user-oriented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose the right technology:
&lt;/h3&gt;

&lt;p&gt;To choose the right technology for your fintech application, you need to clearly define the features and functionalities that you will be integrated. The technology you choose should allow you to add new features quickly and make changes when necessary, without affecting the functionality of the entire application.&lt;/p&gt;

&lt;p&gt;Your selected technology plays a major role in deciding the future of your application and choosing the wrong tech stack can cause you the loss of money, time, and resources for your project.&lt;/p&gt;

&lt;p&gt;Firstly, you need to choose the right architecture. An application architecture determines how all the components will organize and communicate with each other.&lt;/p&gt;

&lt;p&gt;After choosing the best architecture for your fintech app, you need to select a programming language. There are many programming languages to develop an application. The language of choice often dictates the cost and time needed for development.&lt;/p&gt;

&lt;p&gt;For the mobile version of your application, you can choose between native app development (building separate apps for Android and IOS), or cross-platform development (writing a single codebase for both).&lt;/p&gt;

&lt;p&gt;To minimize the time of your application development, you can consider using cross-platform technologies such as React Native or flutter. (Watch out for my next article on choosing the best technology for your fintech app).&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it simple, make it user-friendly:
&lt;/h3&gt;

&lt;p&gt;Fintech applications are meant to be user-friendly. That’s the reason they are designed for. Customers know nothing about the coding, what they praise is simplicity, transparency, and a nice user interface. &lt;/p&gt;

&lt;p&gt;Good UI/UX is the second most important thing talking about Fintech applications after security. Keep it simple by ensuring everything your user might need is available on the dashboard without tons of unnecessary features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop an MVP:
&lt;/h3&gt;

&lt;p&gt;A minimum viable product aims at testing the application before launching it. It’s simply a basic version of the app that includes its fundamental components and features. &lt;/p&gt;

&lt;p&gt;That’s enough for the users to try it, and also a chance to attract new investors. Getting feedback from real users will show you if there are any weaknesses and also you’ll easily find out what features should be added next. #fintech #softwaredevelopment #Application&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>finance</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Building a Full-stack Invoicing Application using the Novu API</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Mon, 12 Jun 2023 22:23:03 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/exploring-the-power-of-the-novu-api-for-building-a-full-stack-invoicing-application-4cgh</link>
      <guid>https://forem.com/jamesoyanna/exploring-the-power-of-the-novu-api-for-building-a-full-stack-invoicing-application-4cgh</guid>
      <description>&lt;p&gt;Invoicing is an essential aspect of running a business, and having an efficient invoicing system can greatly streamline operations. &lt;/p&gt;

&lt;p&gt;With the advancements in technology, developers now have access to powerful APIs that simplify the process of creating and sending invoices.&lt;/p&gt;

&lt;p&gt;One such API is the Novu API, which empowers developers to build robust and feature-rich invoicing applications. &lt;/p&gt;

&lt;p&gt;This article explores the power of the Novu API and how it can be leveraged to create a full-stack invoicing application.&lt;/p&gt;

&lt;p&gt;You will be building a fullstack invoicing application for creating and Sending invoices to customers via email. This application will be useful for Startups, Business Owners and Freelancers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Invoice Creation:
&lt;/h4&gt;

&lt;p&gt;The application provides a user-friendly interface for creating invoices.&lt;/p&gt;

&lt;p&gt;Users can input relevant details such as the customer's name, billing information, item descriptions, quantities, prices, and notes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Invoice Sending:
&lt;/h4&gt;

&lt;p&gt;You will integrate the Novu API, that would enable you to send invoices in PDF format directly to customers via email.&lt;/p&gt;

&lt;h4&gt;
  
  
  Edit Invoice Functionality:
&lt;/h4&gt;

&lt;p&gt;To cater to for changing requirements or corrections, you will incorporate an edit invoice functionality.&lt;/p&gt;

&lt;p&gt;Here is the link to the repository of the application with the full code implementation -&lt;a href="https://github.com/jamesoyanna/novu-invoice" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a link to the demo of the application - &lt;a href="https://novu-invoice.netlify.app/" rel="noopener noreferrer"&gt;Novu Invoice Application&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a screenshot of the final look of the application:&lt;/p&gt;

&lt;p&gt;Frontend Page View :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2z842dby51bp0k066n3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2z842dby51bp0k066n3.PNG" alt="Front page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invoice Creation View:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoahwnhnkuzki7e6842x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoahwnhnkuzki7e6842x.PNG" alt="Invoice Creation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Created Invoice View:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0yjb6g1caz85n2u89bx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0yjb6g1caz85n2u89bx.PNG" alt="Created Invoice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sample Invoice:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F375yjmeudvfunlsq605i.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F375yjmeudvfunlsq605i.PNG" alt="Sample Invoice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Overview of the Novu API:
&lt;/h4&gt;

&lt;p&gt;The Novu API is a unified delivery API that would allow you to send invoices as email messages to customers seamlessly. &lt;/p&gt;

&lt;p&gt;You can read more about it on the &lt;a href="https://novu.co/" rel="noopener noreferrer"&gt;Novu Website&lt;/a&gt;. You can also read-up on the documentation &lt;a href="https://docs.novu.co/overview/introduction/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It provides a straightforward integration process, making it an excellent choice for developers looking to incorporate invoicing functionality into their applications. &lt;/p&gt;

&lt;p&gt;The API handles the complexities of email delivery, ensuring that invoices reach customers' inboxes reliably.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;The technologies you will be using for the development of this application are; *&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React JS -Library for building your user interface&lt;/li&gt;
&lt;li&gt;Axios - Promise based HTTP client for the browser and node.js&lt;/li&gt;
&lt;li&gt;React-router - Enables the implementation of dynamic routing in a web applications.&lt;/li&gt;
&lt;li&gt;Tailwind CSS - A utility-first CSS framework for your styling.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Novu/node - Simple components and APIs for managing all communication channels in one place: Email, SMS, Direct, and Push&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Express JS - flexible Node.js web application framework that provides a robust set of features for web and mobile applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTML-PDF - HTML to PDF converter that uses phantomjs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mongoose - Provides a straight-forward, schema-based solution to model our application data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js- Cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let's start building.&lt;/strong&gt;&lt;br&gt;
Create a folder for your project. Name it &lt;code&gt;novu-invoice&lt;/code&gt; or you can name it anything you like.&lt;/p&gt;

&lt;p&gt;Now, you will start with building the API or backend of the application first. &lt;/p&gt;

&lt;p&gt;Inside the novu-invoice folder you have just created, create another folder. Name it &lt;code&gt;backend&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open your command-line inside the backend folder and type:&lt;br&gt;
&lt;code&gt;npm  init --y&lt;/code&gt;  to initiate your API application.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;package.json&lt;/code&gt; file is automatically generated for you.&lt;/p&gt;

&lt;p&gt;Your package.json file should look like this -&lt;br&gt;
&lt;code&gt;{&lt;br&gt;
  "name": "backend",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "description": "",&lt;br&gt;
  "main": "index.js",&lt;br&gt;
  "scripts": {&lt;br&gt;
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"&lt;br&gt;
  },&lt;br&gt;
  "keywords": [],&lt;br&gt;
  "author": "",&lt;br&gt;
  "license": "ISC"&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up the Server:
&lt;/h3&gt;

&lt;p&gt;Now, install the necessary dependencies you will be needing for this project by running this command:&lt;br&gt;
&lt;code&gt;npm i  npm i express mongoose cors html-pdf moment pdfkit uuid @novu/node dotenv nodemon&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will install all the dependencies.&lt;/p&gt;

&lt;p&gt;Inside your &lt;code&gt;backend&lt;/code&gt; folder, create a file. Name it &lt;code&gt;app.js&lt;/code&gt; and setup a simple express server in it by adding the code below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, you imported the Express.js module, which is a web application framework for Node.js.&lt;/p&gt;

&lt;p&gt;You created an instance of the Express application with the code - &lt;code&gt;const app = express();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You add a middleware to our application. In this case, &lt;code&gt;express.json()&lt;/code&gt;, used to parse incoming JSON data. &lt;/p&gt;

&lt;p&gt;This allows you to easily handle JSON payloads in your application routes.&lt;/p&gt;

&lt;p&gt;You then setup a simple route for the root URL ("/") such that when a GET request is made to the root URL, the callback function &lt;code&gt;(req, res) =&amp;gt; { ... }&lt;/code&gt; is executed. &lt;/p&gt;

&lt;p&gt;And then lastly, you specify a port on which the server will listen for incoming requests.&lt;/p&gt;

&lt;p&gt;In this case, it is set to port 5000. The &lt;code&gt;app.listen()&lt;/code&gt; function starts the server and listens on the specified port. &lt;/p&gt;

&lt;p&gt;Once the server is running, it logs a message to the console indicating that the app is running and on that port.&lt;/p&gt;

&lt;p&gt;Update your package.json by adding this start script - &lt;code&gt;"start": "nodemon app.js"&lt;/code&gt; in the script section. Your package.json file should now look like this.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To start your server, run the command - &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This would display this on your command line, indicating the server is working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdrxljdrco98oz6ybadk.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdrxljdrco98oz6ybadk.PNG" alt="Server Running"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Establish Database Connection:
&lt;/h3&gt;

&lt;p&gt;Now, implement a database connection to your application.&lt;/p&gt;

&lt;p&gt;In your root directory, create a file. Name it &lt;code&gt;db.js&lt;/code&gt; and add the following code inside:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you are establishing a connection to a MongoDB database using Mongoose, a popular MongoDB object modeling tool for Node.js.&lt;/p&gt;

&lt;p&gt;Firstly, you imported the Mongoose module. You then define an asynchronous function called &lt;code&gt;connectToDatabase&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You establish a connection to the MongoDB database using the &lt;code&gt;mongoose.connect()&lt;/code&gt; method. The connection string is provided as the argument, which is stored in the &lt;code&gt;MONGODB_URI&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;If the database connection is successful, you log a success message to the console.&lt;/p&gt;

&lt;p&gt;You exported the &lt;code&gt;connectToDatabase&lt;/code&gt; function, allowing other parts of our application to import and use it.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;app.js&lt;/code&gt; file, import the &lt;code&gt;connectToDatabase&lt;/code&gt; function and invoke it. Add the following code to your &lt;code&gt;app.js&lt;/code&gt; file like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const connectToDatabase = require("./db");&lt;br&gt;
.......&lt;br&gt;
connectToDatabase();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;app.js&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now create a file. Name it &lt;code&gt;.env&lt;/code&gt; in your root directory and add the following code:&lt;br&gt;
&lt;code&gt;MONGODB_URI = mongodb://localhost:27017/novu-invoice&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file you created is to securely manage configuration variables or environment-specific settings for your application.&lt;/p&gt;

&lt;p&gt;It allows you to separate sensitive or environment-specific configuration from your application code in this case, you have store MongoDB connection url on it.&lt;/p&gt;

&lt;p&gt;Please ensure you setup a MongoDB Database either locally using using the MongoDB Compass(You can do that &lt;a href="https://medium.com/@LondonAppBrewery/how-to-download-install-mongodb-on-windows-4ee4b3493514" rel="noopener noreferrer"&gt;here&lt;/a&gt; or on the cloud using the MongoDB Atlas.&lt;/p&gt;

&lt;p&gt;You have also installed &lt;code&gt;Nodemon&lt;/code&gt;, a library that helps you to automatically restart our server. You can also run &lt;code&gt;npm start&lt;/code&gt; if you have terminate the process before.&lt;/p&gt;

&lt;p&gt;If everything works fine, you should see this in your console indicating the database is successfully connected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gt516kak85kofcz3bz0.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gt516kak85kofcz3bz0.PNG" alt="DB Connected"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implement Database Model:
&lt;/h3&gt;

&lt;p&gt;Now, implement your database model. &lt;br&gt;
Create a folder in your project directory. Name it &lt;code&gt;model&lt;/code&gt;. Inside this folder, create a file. Name it &lt;code&gt;invoiceModel.js&lt;/code&gt; and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported the necessary modules from the Mongoose library. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;const invoiceSchema = new Schema({&lt;br&gt;
  // Schema properties and their types&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, you created a new Mongoose schema named &lt;code&gt;invoiceSchema&lt;/code&gt; using the Schema object. The schema defines the structure and properties of the "Invoice" document stored in the MongoDB collection.&lt;/p&gt;

&lt;p&gt;You then define the properties of the Invoice schema. Each property corresponds to a field in the "Invoice" document. &lt;/p&gt;

&lt;p&gt;The properties can have various types such as Date, String, or Number. The &lt;code&gt;items&lt;/code&gt; property is an array that contains objects with properties such as &lt;code&gt;itemName&lt;/code&gt;, &lt;code&gt;unitPrice&lt;/code&gt;, and &lt;code&gt;quantity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createdAt&lt;/code&gt;property is a special field that automatically gets assigned the current date and time when a new document is created.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;module.exports = model('Invoice', invoiceSchema);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, you exported the Mongoose model for the "Invoice" schema. The model function is used to create a model from the &lt;code&gt;invoiceSchema&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The model is given a name 'Invoice', which corresponds to the MongoDB collection name. The exported model can then be used to perform database operations on the "Invoice" collection.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implement Invoice Controller:
&lt;/h3&gt;

&lt;p&gt;Create a folder and name it &lt;code&gt;controller&lt;/code&gt;. Inside the controller folder, create a file. Name it &lt;code&gt;invoiceController.js&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, you require the Mongoose library and an invoice model from the model directory.&lt;/p&gt;

&lt;p&gt;You define a function called &lt;code&gt;createInvoice&lt;/code&gt; that handles the creation of an invoice. &lt;/p&gt;

&lt;p&gt;It extracts the necessary data from the request body, generates a random 6-digit invoice number with the prefix "INV," and then creates a new invoice using the InvoiceModel. &lt;/p&gt;

&lt;p&gt;The new invoice is then sent as a JSON response with a status code of 201 (created).&lt;/p&gt;

&lt;p&gt;You then define another function to handle the editing of an invoice. &lt;br&gt;
It extracts the invoice ID from the request parameters and the invoice data from the request body. &lt;/p&gt;

&lt;p&gt;It then checks if the provided invoice ID is a valid MongoDB object ID. If not, it sends a 404 response with the message "No invoice with that id." &lt;/p&gt;

&lt;p&gt;If the ID is valid, it updates the invoice using the InvoiceModel's &lt;code&gt;findByIdAndUpdate&lt;/code&gt; method, passing the ID, the invoice data, and the option { new: true } to return the updated invoice. The updated invoice is then sent as a JSON response.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implement Routing:
&lt;/h3&gt;

&lt;p&gt;To implement your routes, create a folder. Name it &lt;code&gt;routes&lt;/code&gt;. Inside it, create a file. Name it &lt;code&gt;invoiceRoute.js&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported the Express library and the other controller functions from controllers folder. &lt;/p&gt;

&lt;p&gt;The controller functions handle the logic for creating and editing an invoice.&lt;/p&gt;

&lt;p&gt;You created an instance of the Express router by calling &lt;code&gt;express.Router()&lt;/code&gt;. The router allows you to define routes for specific HTTP methods and attach the corresponding controller functions to them.&lt;/p&gt;

&lt;p&gt;You define the following routes using the router:&lt;/p&gt;

&lt;h5&gt;
  
  
  POST: /
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;This route is used to create a new invoice. It calls the &lt;code&gt;createInvoice&lt;/code&gt; controller function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  PATCH /:id
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;This route is used to update an existing invoice based on the id parameter. It calls the &lt;code&gt;editInvoice&lt;/code&gt; controller function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now make use of your routes in the &lt;code&gt;app.js&lt;/code&gt; file. &lt;br&gt;
In your &lt;code&gt;app.js&lt;/code&gt; file import the invoice route by requiring it like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const invoiceRoutes = require('./routes/invoiceRoute')&lt;/code&gt;&lt;br&gt;
And use it like this:&lt;br&gt;
&lt;code&gt;app.use('/api/invoices', invoiceRoutes);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;app.js&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Designing the Invoice Template:
&lt;/h3&gt;

&lt;p&gt;In this section you will be designing the way your invoice will look like. &lt;/p&gt;

&lt;p&gt;Inside your project folder, create a folder. Name it &lt;code&gt;document&lt;/code&gt;. Inside the document folder create a file. Name it &lt;code&gt;index.js&lt;/code&gt; and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code you are basically defining a JavaScript function called &lt;code&gt;pdfTemplate&lt;/code&gt; that generates an HTML template for your invoice.&lt;/p&gt;

&lt;p&gt;The pdfTemplate function takes an object as an argument containing various properties related to an invoice, such as name, phoneNumber, email, notes, items, dueDate, issuedDate, totalQuantity, totalAmount, and invoiceNumber. &lt;/p&gt;

&lt;p&gt;It uses these properties to populate the invoice template.&lt;/p&gt;

&lt;p&gt;The returned HTML template can then be used to generate PDF documents or display the invoice in an HTML format.&lt;/p&gt;

&lt;p&gt;You will import the invoice template into our &lt;code&gt;app.js&lt;/code&gt; file and use it later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the Novu API:
&lt;/h3&gt;

&lt;p&gt;Novu provides a unified API that makes it simple to send notifications through multiple channels, including In-App, Push, Email, SMS, and Chat. &lt;/p&gt;

&lt;p&gt;With Novu, you can create custom workflows and define conditions for each channel, ensuring that your notifications are delivered in the most effective way possible. You can read more about the Novu API in their &lt;a href="https://docs.novu.co" rel="noopener noreferrer"&gt;Official Doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You will need to sign up for a &lt;a href="https://web.novu.co/auth/login" rel="noopener noreferrer"&gt;Novu account&lt;/a&gt; to get started&lt;/p&gt;

&lt;p&gt;After setting up an account, the next step involves creating a workflow within the workflow tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewr5qp4ajf8ewt6r637z.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewr5qp4ajf8ewt6r637z.PNG" alt="Workflow tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you added the email event below the Trigger by dragging and dropping it as the event that will happen whenever a notification is triggered. &lt;/p&gt;

&lt;p&gt;So you are setting up one that works for sending emails, as you want to send invoice as an email.&lt;/p&gt;

&lt;p&gt;Click on the email channel you just added and fill-in the required information and click on the update button to save your changes like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flkpaifbtpxxltdjou3tn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flkpaifbtpxxltdjou3tn.PNG" alt="Workflow Email field"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to your settings tab still in your Novu Dashboard, copy the API Key and add it to your environment variable like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j5mzyhj2pmouzwl80nv.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j5mzyhj2pmouzwl80nv.PNG" alt="API Key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;.env&lt;/code&gt; file, add the api key you have just copied like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NOVU_API_KEY= your-novu-api&lt;/code&gt;. Replace the value with your &lt;code&gt;Novu&lt;/code&gt; API Key.&lt;/p&gt;

&lt;p&gt;One more thing you will add to your implementation is the &lt;code&gt;TRIGGER_NAME&lt;/code&gt;. You will get this by clicking on the Workflow tab and locate the settings area like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh75g17wtbe5olh8uogjm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh75g17wtbe5olh8uogjm.PNG" alt="Workflow settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the &lt;code&gt;TRIGGER_NAME&lt;/code&gt; which is our identifier is&lt;code&gt;invoice-notification&lt;/code&gt;. Copy your identifier and save it somewhere. You will need it for your implementation. &lt;/p&gt;

&lt;p&gt;Now, implement the Novu API. But before that, require some of the dependencies you will be using. Add the following to your &lt;code&gt;app.js&lt;/code&gt; file&lt;br&gt;
&lt;code&gt;&lt;br&gt;
const { Novu } = require('@novu/node');&lt;br&gt;
const pdf = require('html-pdf');&lt;br&gt;
const cors = require('cors');&lt;br&gt;
const fs = require('fs');&lt;br&gt;
const pdfTemplate = require('./document/index');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// Enable CORS middleware&lt;br&gt;
app.use(cors());&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here in this code above, you imported several Node.js modules: @novu/node, html-pdf, cors, fs, and a custom module pdfTemplate.&lt;/p&gt;

&lt;p&gt;You also imported or require the pdfTemplate you have previously created.&lt;/p&gt;

&lt;p&gt;Then you added the CORS middleware to the Express application using this code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.use(cors());&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The application enables CORS and allows cross-origin requests from different domains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add the logic for sending the invoice as PDF like this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you define an object &lt;code&gt;options&lt;/code&gt; with a property format set to 'A4'. These options are used when generating the PDF document using the html-pdf library. In this case, the A4 format is specified.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.post('/send-pdf', (req, res) =&amp;gt; { ... });&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You then sets up a route handler for the POST request to the &lt;code&gt;/send-pdf&lt;/code&gt; endpoint. &lt;/p&gt;

&lt;p&gt;You listen for incoming requests and executes the provided callback function when the endpoint is accessed via a POST request.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const { email } = req.body;&lt;/code&gt;&lt;br&gt;
You extracted the email property from the request body using destructuring assignment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pdf.create(pdfTemplate(req.body), options).toFile('invoice.pdf', (err) =&amp;gt; { ... });&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
You generated a PDF document using the &lt;code&gt;pdfTemplate&lt;/code&gt; function and the options defined earlier. &lt;/p&gt;

&lt;p&gt;You executed the &lt;code&gt;pdfTemplate&lt;/code&gt; function with the request body as an argument. The resulting PDF document is saved to a file named 'invoice.pdf'.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const novu = new Novu(process.env.NOVU_API_KEY);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With this code above, you created a new instance of the &lt;code&gt;Novu&lt;/code&gt; object, which was imported earlier from the &lt;code&gt;@novu/node&lt;/code&gt;module. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;novu.trigger('invoice-notification', { ... });&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, you invoke the trigger method of &lt;code&gt;the novu&lt;/code&gt; object, passing 'invoice-notification' as the first argument and an object containing notification details as the second argument. (Remember to replace the identifier with your own TRIGGER_NAME or identifier you had earlier saved.&lt;/p&gt;

&lt;p&gt;The details include the recipient's subscriber ID (Remember to replace the subscriber ID with the one on your Novu dashboard) and email address, and an attachment object representing the invoice in PDF format.&lt;/p&gt;

&lt;p&gt;It reads the contents of the PDF file using &lt;code&gt;fs.readFileSync&lt;/code&gt; and converts it to a base64-encoded string before attaching it to the payload.&lt;/p&gt;

&lt;p&gt;What you have basically done was to handle a POST request to generate a PDF invoice, save it to a file, and trigger a notification using the &lt;code&gt;Novu&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;app.js&lt;/code&gt; should finally look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You are done with the backend of our Novu Invoice project. You can test your endpoints using Postman like this:&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing the create invoice endpoint:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm90qdmeowo2oczzxre7b.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm90qdmeowo2oczzxre7b.PNG" alt="Create Invoice Endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Developing the frontend of your Invoice Application:
&lt;/h3&gt;

&lt;p&gt;In this section, you will be developing the frontend of your invoice application. &lt;/p&gt;

&lt;p&gt;Inside your project directory where you have your backend folder,&lt;br&gt;
initialize a new react application by running:&lt;br&gt;
&lt;code&gt;npx create-react-app frontend&lt;/code&gt; on your command line.&lt;/p&gt;

&lt;p&gt;This would create a new &lt;code&gt;frontend&lt;/code&gt;folder for your application.&lt;/p&gt;

&lt;p&gt;Navigate into the &lt;code&gt;frontend&lt;/code&gt; folder from your command line and install the Tailwindcss  to add styling to your application using the following command: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -D tailwindcss&lt;/code&gt; and then run&lt;br&gt;
&lt;code&gt;npx tailwindcss init&lt;/code&gt; to initialize the Tailwindcss. This will automatically generate a &lt;code&gt;tailwind.config&lt;/code&gt; file for the setup.&lt;/p&gt;

&lt;p&gt;Now open the application in VSCode or in any of your favorite editor. &lt;/p&gt;

&lt;p&gt;Remove the default content in the tailwind.config and add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/** @type {import('tailwindcss').Config} */&lt;br&gt;
module.exports = {&lt;br&gt;
  content: [&lt;br&gt;
    "./src/**/*.{js,jsx,ts,tsx}",&lt;br&gt;
  ],&lt;br&gt;
  theme: {&lt;br&gt;
    extend: {},&lt;br&gt;
  },&lt;br&gt;
  plugins: [],&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;index.css&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt;folder of your project directory. Remove its content and add the following code:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
@tailwind base;&lt;br&gt;
@tailwind components;&lt;br&gt;
@tailwind utilities;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now start your application by running this command:&lt;br&gt;
&lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will start the application on port 3000. Go to your browser. You should see your application running on &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqapz797kvvvqq42pl1w.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqapz797kvvvqq42pl1w.PNG" alt="React App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now do some cleaning on your application and also test your tailwind styling to ensure its working.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;app.js&lt;/code&gt; file, remove it's content and add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export default function App() {&lt;br&gt;
  return (&lt;br&gt;
    &amp;lt;h1 className="text-3xl font-bold underline bg-green-600"&amp;gt;&lt;br&gt;
      Novu Invoice&lt;br&gt;
    &amp;lt;/h1&amp;gt;&lt;br&gt;
  )&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After applying the tailwind styling, your application should now look like this on your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6r7la13dd7ppnb3snuj.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6r7la13dd7ppnb3snuj.PNG" alt="Tailwind style"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now implement routing:&lt;br&gt;
Firstly, you will need to install the &lt;code&gt;react-router-dom&lt;/code&gt; library for your routing. Stop your server and run the command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i react-router-dom&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;src&lt;/code&gt; folder, create a folder. Name it &lt;code&gt;components&lt;/code&gt;. Inside the components folder, create a file and name it &lt;code&gt;Invoice.jsx&lt;/code&gt; and add the following code. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here you just create a simple component to render invoice as text.&lt;/p&gt;

&lt;p&gt;Now, update the &lt;code&gt;index.js&lt;/code&gt; file with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported the necessary modules from the react, react-dom, and react-router-dom libraries.&lt;/p&gt;

&lt;p&gt;You also imported the &lt;code&gt;Invoice&lt;/code&gt; component you had created earlier.&lt;/p&gt;

&lt;p&gt;You created a router using &lt;code&gt;createBrowserRouter&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Router is configured with an array containing a single route object:&lt;/p&gt;

&lt;p&gt;The route object specifies the path as "/" (root path) and associates it with the &lt;code&gt;Invoice&lt;/code&gt; component meaning that when the root path is accessed, the &lt;code&gt;Invoice&lt;/code&gt; component will be rendered.&lt;/p&gt;

&lt;h4&gt;
  
  
  Add Logo:
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;src&lt;/code&gt; folder, create a folder name it &lt;code&gt;images&lt;/code&gt; and add any image of your choice as logo. &lt;/p&gt;

&lt;h4&gt;
  
  
  Creating the Invoice Header:
&lt;/h4&gt;

&lt;p&gt;Now, create a file inside your component folder. Name it &lt;code&gt;InvoiceHeader.jsx&lt;/code&gt; and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you define a React functional component called &lt;code&gt;InvoiceHeader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You added your logo by importing it from the images folder. &lt;/p&gt;

&lt;p&gt;You imported &lt;code&gt;Link&lt;/code&gt; from "react-router-dom", a package used for routing in React applications. It will allow you create links to different routes within the application.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InvoiceHeader&lt;/code&gt; component renders a header section for your invoice which includes a logo, title, location information, and an invoice number label. &lt;/p&gt;

&lt;p&gt;The logo is wrapped in a link that navigates to the root path when clicked. &lt;/p&gt;

&lt;p&gt;Import the &lt;code&gt;InvoiceHeader&lt;/code&gt; component into the Invoice component. Your Invoice component should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported the &lt;code&gt;InvoiceHeader&lt;/code&gt; from the './InvoiceHeader' file.&lt;/p&gt;

&lt;p&gt;A container is rendered with a specified width and styling, and includes the &lt;code&gt;InvoiceHeader&lt;/code&gt; component as its child, which renders the header section of the invoice. &lt;/p&gt;

&lt;p&gt;Your application should now look like this on your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcn9woxen2wwt6jfrjfv.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcn9woxen2wwt6jfrjfv.PNG" alt="Front page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Add Invoice FormField:
&lt;/h4&gt;

&lt;p&gt;Now, create a file inside your component folder. Name it &lt;code&gt;FormField.jsx&lt;/code&gt; and add the following code to it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here  in this code, you define the &lt;code&gt;FormField&lt;/code&gt; component as an arrow function that takes in a destructured object as its parameter. &lt;/p&gt;

&lt;p&gt;This object contains the following properties; &lt;br&gt;
label: Represents the label text for the form field.&lt;/p&gt;

&lt;p&gt;name: Represents the name attribute of the input field.&lt;/p&gt;

&lt;p&gt;type: Represents the type attribute of the input field (e.g., "text", "number", "email").&lt;/p&gt;

&lt;p&gt;value: Represents the current value of the input field.&lt;/p&gt;

&lt;p&gt;onChange: Represents the callback function to handle the onChange event of the input field.&lt;/p&gt;

&lt;p&gt;placeholder: Represents the placeholder text for the input field.&lt;/p&gt;

&lt;p&gt;error: Represents an optional error message to be displayed.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;FormField&lt;/code&gt; component represents a form field with a label, input field, and optional error message. &lt;/p&gt;

&lt;p&gt;It provides props for configuring various attributes and behavior of the form field, such as label text, input type, value, onChange event handler, placeholder, and error message.&lt;/p&gt;

&lt;p&gt;You will be defining these &lt;code&gt;props&lt;/code&gt; in the &lt;code&gt;Invoice&lt;/code&gt; component shortly.&lt;/p&gt;

&lt;p&gt;Now use your &lt;code&gt;FormField&lt;/code&gt;component in the Invoice component. You will also be adding a table and a button. Update your &lt;code&gt;Invoice.jsx&lt;/code&gt; file  with this code: &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported the &lt;code&gt;FormField&lt;/code&gt;. You rendered a form layout inside a flex container with centered content and a margin-top. &lt;/p&gt;

&lt;p&gt;You included the &lt;code&gt;InvoiceHeader&lt;/code&gt; component to display the invoice header section.&lt;/p&gt;

&lt;p&gt;The form includes fields for billing information, such as the recipient's name and the issued date. It also includes fields for contact information, such as email address, phone number, and due date.&lt;/p&gt;

&lt;p&gt;You added a table to be used for inputting item descriptions, quantities, prices, and amounts. &lt;code&gt;Add Item&lt;/code&gt; button is present to add new items to the invoice.&lt;/p&gt;

&lt;p&gt;Invoice summary section displays the total quantity and total amount of the invoice.&lt;/p&gt;

&lt;p&gt;You added "Create Invoice" button at the end of the form for creating the invoice.&lt;/p&gt;

&lt;p&gt;Your application should now look like this on your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feib6aaanru6t2ze3eggw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feib6aaanru6t2ze3eggw.PNG" alt="Invoice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, define the different states to be used in your application. &lt;/p&gt;

&lt;p&gt;You will be adding the &lt;code&gt;invoiceData&lt;/code&gt;, error and isLoading to track the state in your application and to also update the state.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;Invoice.jsx&lt;/code&gt; file with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code , you imported &lt;code&gt;useState&lt;/code&gt; hook from the "react" module and &lt;code&gt;useNavigate&lt;/code&gt; from &lt;code&gt;"react-router-dom"&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;Then you initialized state variables using the &lt;code&gt;useState&lt;/code&gt; hook:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;isLoading: &lt;br&gt;
A boolean state to track the loading state of the component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;errors: &lt;br&gt;
An object that holds error messages for form fields.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;invoiceData:&lt;br&gt;
 An object that stores the data related to the invoice, including name, phoneNumber, email, issuedDate, dueDate, items (an array of item details), notes, total, invoiceNumber, totalQuantity, and totalAmount.&lt;/p&gt;

&lt;p&gt;You defined a navigate function using the &lt;code&gt;useNavigate&lt;/code&gt; hook from &lt;code&gt;"react-router-dom"&lt;/code&gt;. It allows you to navigate to different routes in our application.&lt;/p&gt;

&lt;p&gt;You added event handlers as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;handleInputChange:&lt;br&gt;
Handles the input change for form fields and updates the invoiceData state accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;handleItemChange: &lt;br&gt;
Handles the input change for individual item fields in the items array and updates the &lt;code&gt;invoiceData&lt;/code&gt; state. It also calls the&lt;code&gt;updateTotals&lt;/code&gt; function to recalculate the total quantity and total amount.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;handleAddItem:&lt;br&gt;
Adds a new item object to the &lt;code&gt;invoiceData&lt;/code&gt; state's items array. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;handleRemoveItem:&lt;br&gt;
Removes an item object from the invoiceData state's items array.&lt;/p&gt;

&lt;p&gt;updateTotals:&lt;br&gt;
Calculates the total quantity and total amount based on the items' quantity and unit price. It updates the &lt;code&gt;invoiceData&lt;/code&gt; state accordingly.&lt;/p&gt;

&lt;p&gt;Now, you will refactor our code a bit. You will extract the invoice items into it's own component. &lt;/p&gt;

&lt;p&gt;Create a file inside the component folder. Name it &lt;code&gt;InvoiceItem.jsx&lt;/code&gt; and add the following code to it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you defined the &lt;code&gt;InvoiceItem&lt;/code&gt; functional component, which represents a single row in the invoice table for an item.&lt;/p&gt;

&lt;p&gt;The component receives &lt;code&gt;props&lt;/code&gt; as its parameter. The props include:&lt;/p&gt;

&lt;p&gt;item: An object containing the details of the item (e.g., itemName, quantity, unitPrice).&lt;/p&gt;

&lt;p&gt;index: The index of the item in the list of items.&lt;/p&gt;

&lt;p&gt;onChange: A callback function to handle changes in the item's input fields.&lt;/p&gt;

&lt;p&gt;onRemove: A callback function to handle removing the item from the list.&lt;/p&gt;

&lt;p&gt;This component returns JSX markup, representing a table row (&lt;/p&gt;
&lt;tr&gt;) with several table cells (&lt;td&gt;).

&lt;p&gt;Each table cell contains an  element for user input or display of item details.&lt;/p&gt;

&lt;p&gt;You will use this component inside your Invoice component later.&lt;/p&gt;

&lt;p&gt;Now before you start using our state variables and the functions, you defined in the &lt;code&gt;Invoice&lt;/code&gt; component, integrate your backend API with the frontend. &lt;/p&gt;

&lt;p&gt;Run the command &lt;code&gt;npm i axios&lt;/code&gt; to install the axios library for making http calls to the server. If your React app is still running, you will need to stop the server before installing the library.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src&lt;/code&gt;, create a file. Name it &lt;code&gt;api.js&lt;/code&gt;and add the following code to it:-&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported &lt;code&gt;axios&lt;/code&gt; for making HTTP requests to our API.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;create&lt;/code&gt; method, you created an Axios instance. The method accepts an object with configuration options as its parameter. &lt;/p&gt;

&lt;p&gt;In this case, the configuration object contains a single property, &lt;code&gt;baseURL&lt;/code&gt;  which Specifies the base URL for all the requests made using the Axios instance.&lt;/p&gt;

&lt;p&gt;Now update your &lt;code&gt;Invoice.jsx&lt;/code&gt; with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you defined several event handler functions used in the form:&lt;/p&gt;

&lt;p&gt;navigateTo: Use this navigate function to navigate to a specified route with optional state data.&lt;/p&gt;

&lt;p&gt;handleCreateInvoice: An asynchronous function that handles the creation of the invoice. &lt;/p&gt;

&lt;p&gt;It performs validation on the form fields, sends a POST request to the server using the api object, handles the response, and redirects to the invoice details page.&lt;/p&gt;

&lt;p&gt;handleInputChange: function updates the corresponding field value in the invoiceData state object when an input field's value changes.&lt;/p&gt;

&lt;p&gt;handleItemChange: function to update the details of an individual invoice item in the &lt;code&gt;invoiceData&lt;/code&gt; state object when the corresponding input field's value changes. &lt;/p&gt;

&lt;p&gt;It also calls the &lt;code&gt;updateTotals&lt;/code&gt; function to recalculate the total quantity and total amount.&lt;/p&gt;

&lt;p&gt;handleAddItem: A function that adds a new empty item to the items array in the &lt;code&gt;invoiceData&lt;/code&gt; state object.&lt;/p&gt;

&lt;p&gt;handleRemoveItem: this function removes an item from the items array in the invoiceData state object.&lt;/p&gt;

&lt;p&gt;updateTotals: function calculates the total quantity and total amount based on the items' quantities and unit prices and updates the corresponding fields in the &lt;code&gt;invoiceData&lt;/code&gt; state object.&lt;/p&gt;

&lt;p&gt;Upon clicking the &lt;code&gt;Create Invoice&lt;/code&gt; button to create your invoice, you need to set a page that you will use to display the detail of the invoice you have created.&lt;/p&gt;

&lt;p&gt;Now set it up. Inside your component folder, create a file. Name it &lt;code&gt;InvoiceDetails.jsx&lt;/code&gt; and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, you imported several dependencies and defined the &lt;code&gt;InvoiceDetails&lt;/code&gt; component that renders the invoice details form.&lt;/p&gt;

&lt;p&gt;Inside the component, you used the &lt;code&gt;useLocation&lt;/code&gt; hook to get the current location object from the React Router.&lt;/p&gt;

&lt;p&gt;You initialized the &lt;code&gt;initialInvoiceData&lt;/code&gt; variable with the &lt;code&gt;invoiceData&lt;/code&gt; value from the location state. The ?. operator is used for optional chaining to prevent errors if &lt;code&gt;location.state&lt;/code&gt; or &lt;code&gt;location.state.invoiceData&lt;/code&gt;is undefined.&lt;/p&gt;

&lt;p&gt;You defined the &lt;code&gt;navigateTo&lt;/code&gt; function to navigate to a specified route when called. It uses the navigate function from &lt;code&gt;useNavigate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You defined the &lt;code&gt;handleGoBack&lt;/code&gt; function to navigate back to the home page when called. It calls the &lt;code&gt;navigateTo&lt;/code&gt; function with the "/" route.&lt;/p&gt;

&lt;p&gt;You defined the &lt;code&gt;handleSendInvoice&lt;/code&gt; function as an asynchronous function. It is called when the &lt;code&gt;"Send Invoice"&lt;/code&gt; button is clicked&lt;/p&gt;

&lt;p&gt;It sends the invoice data to the server using the &lt;code&gt;api.post&lt;/code&gt; method and updates the loading, error, and success states based on the response.&lt;/p&gt;

&lt;p&gt;You also defined the &lt;code&gt;handleEditInvoice&lt;/code&gt; function as an asynchronous function. It toggles the &lt;code&gt;editMode&lt;/code&gt; state when called. &lt;/p&gt;

&lt;p&gt;If &lt;code&gt;editMode&lt;/code&gt; is true, it calculates the updated total quantity and total amount based on the items in the invoice data, sends a patch request to update the invoice data on the server using the &lt;code&gt;api.patch&lt;/code&gt; method, and updates the success and error states accordingly.&lt;/p&gt;

&lt;p&gt;Also ensure you update your index.js file by importing &lt;code&gt;InvoiceDetails&lt;/code&gt; into it. You use it to handle routing to the details page. &lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;index.js&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;YOU have just completed your fullstack application. You can test its functionalities by creating and invoice, add your email and other information and send the invoice to your email. &lt;/p&gt;

&lt;p&gt;A Message will display showing an Email has been sent to the email you supplied for the receiving of the Invoice.&lt;/p&gt;

&lt;p&gt;Here is the link to the repository of the application with the full code implementation -&lt;a href="https://github.com/jamesoyanna/novu-invoice" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a link to the demo of the application - &lt;a href="https://novu-invoice.netlify.app/" rel="noopener noreferrer"&gt;Novu Invoice Application&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusion: This tutorial provides a details explanation on how you can integrate the Novu API on an Invoice application for sending of invoice via email.&lt;/p&gt;


&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;

</description>
      <category>react</category>
      <category>node</category>
      <category>tailwindcss</category>
      <category>novu</category>
    </item>
    <item>
      <title>Preparing for Your First Software Engineering Job: Key Areas for Junior Developers to Focus On</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Wed, 31 May 2023 10:29:10 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/preparing-for-your-first-software-engineering-job-key-areas-for-junior-developers-to-focus-on-8pm</link>
      <guid>https://forem.com/jamesoyanna/preparing-for-your-first-software-engineering-job-key-areas-for-junior-developers-to-focus-on-8pm</guid>
      <description>&lt;p&gt;As you embark on your journey of learning and developing your technical expertise, it's important to focus on areas that will prepare you for your first software engineering job. &lt;/p&gt;

&lt;p&gt;In this article, we will discuss the key areas you can prioritize to ensure you are well-prepared for the job market as a Backend, Frontend, or full-stack engineer. &lt;/p&gt;

&lt;p&gt;By ticking these boxes in the last lap of your learning, you will equip yourself with the necessary skills to excel in the industry.&lt;/p&gt;

&lt;p&gt;I have assumed you have an appreciable understanding of some technologies you work with.&lt;/p&gt;

&lt;p&gt;I am also assuming you could be joining a standard company that follows the best practices in software development.&lt;/p&gt;

&lt;p&gt;Your typical workday will involve coding and working on tasks. &lt;/p&gt;

&lt;p&gt;Today, you could be debugging and fixing issues, next week you could be implementing new features, or optimizing an existing code. &lt;/p&gt;

&lt;p&gt;Don't be surprised, you may spend a greater part of your time reading the company's codebase and not writing code in your first month or more. &lt;/p&gt;

&lt;p&gt;This might slightly be different for some companies that may expect you to be coding from day one.&lt;/p&gt;

&lt;p&gt;If it's a brownfield application (An application that is already existing) , In some cases, you may not be writing new code from scratch. &lt;/p&gt;

&lt;p&gt;There are already existing components or modules you will be reusing for your work.&lt;/p&gt;

&lt;p&gt;Here are some areas or boxes you should thick in your learning before you join your dream company.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn Coding Standard/Style Guide:
&lt;/h3&gt;

&lt;p&gt;Familiarize yourself with coding standards and best practices established by your company. &lt;/p&gt;

&lt;p&gt;You'll work with your team to follow the coding standards &amp;amp; best practices established by your company. &lt;/p&gt;

&lt;p&gt;Your company will set coding conventions or style guides, guidelines, and rules that you and your team will follow when writing code.&lt;/p&gt;

&lt;p&gt;You are not expected to break these rules. They are already set by software that checks for code quality.&lt;/p&gt;

&lt;p&gt;These standards define a consistent and uniform way of formatting your code, naming variables and functions, organizing code structures,&lt;/p&gt;

&lt;p&gt;The reason for the coding standards is to improve code readability, maintainability, and collaboration with your development team. &lt;/p&gt;

&lt;p&gt;Adopting a widely-used style guide, such as the Airbnb style guide, can help you practice adhering to coding standards from the start.&lt;/p&gt;

&lt;p&gt;For those in the Javascript  &amp;amp; React ecosystem, You can try setting up using this article &lt;a href="https://blog.bitsrc.io/how-to-set-up-airbnb-style-guide-for-react-projects-fc7dfb1f3d68."&gt;Airbnb style guide&lt;/a&gt; and it out in your next hobby project. Start getting used to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Participate in Code Review:
&lt;/h3&gt;

&lt;p&gt;Engage in code reviews to gain experience and improve code quality. Platforms like &lt;a href="https://www.codacy.com/"&gt;Codacy&lt;/a&gt; can assist you by automatically reviewing your code and providing feedback. Embracing code reviews allows you to learn from experienced developers, enhance your coding skills, and maintain high-quality codebases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn Intermediate Git Commands:
&lt;/h3&gt;

&lt;p&gt;Expand your knowledge of Git beyond the basics. I know you are already used to or familiar with the basic git commands. That's fine. You need to step up with these commands:&lt;/p&gt;

&lt;h4&gt;
  
  
  Git stash:
&lt;/h4&gt;

&lt;p&gt;You will need it often to temporarily save changes and not commit them yet so you can switch to another branch to quickly work on a new task assigned to you. &lt;/p&gt;

&lt;p&gt;You can thereafter after comeback to your previous work using the &lt;code&gt;git stash pop&lt;/code&gt; command. &lt;/p&gt;

&lt;h4&gt;
  
  
  Git Rebase:
&lt;/h4&gt;

&lt;p&gt;You will need it so you can incorporate changes from one branch into another so you do not create a new merge commit. &lt;br&gt;
why? because your code reviewer wants you to maintain a clean and linear commit history.&lt;/p&gt;

&lt;h4&gt;
  
  
  Git pull:
&lt;/h4&gt;

&lt;p&gt;You will need to use it often to fetch the latest changes from the remote repository that your developer colleagues have worked on and automatically merges them into your local branch.&lt;/p&gt;

&lt;p&gt;Practicing these commands in your next project will improve your proficiency in version control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace Continuous Learning and Problem-Solving:
&lt;/h3&gt;

&lt;p&gt;Expect challenges in your software engineering career. Embrace them as learning opportunities and take responsibility for your mistakes. Instead of making excuses, offer options and seek solutions. Strive to continuously learn and stay updated with the latest technologies and industry trends. Engage in personal projects and allocate time for self-improvement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Emphasize Collaboration and Communication:
&lt;/h3&gt;

&lt;p&gt;Remember that you are not working alone. Collaborate with your team members, participate in meetings and discussions, and embrace the feedback provided during code reviews. &lt;/p&gt;

&lt;p&gt;Develop effective communication skills to explain your code and ideas clearly. Actively seek guidance and clarification when needed, as this shows your willingness to learn and grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allocate Time for Personal Development:
&lt;/h3&gt;

&lt;p&gt;Invest time in exploring new technologies and expanding your skillset beyond what is used in your workplace. Upskill yourself in areas that may not be provided by your company. This will make you more versatile and future-proof your career.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prioritize Testing in Your Learning:
&lt;/h3&gt;

&lt;p&gt;Incorporate testing as an integral part of your learning process. Building confidence in your code and ensuring code quality through proper testing is crucial. &lt;/p&gt;

&lt;p&gt;By incorporating testing early on, you can catch and prevent bugs before they impact the live application. Understand the importance of unit testing, integration testing, and end-to-end testing in different software development scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improve Your Technical Communication:
&lt;/h3&gt;

&lt;p&gt;Enhance your ability to communicate technical concepts effectively. Practice explaining your code and ideas to others, as this skill will be valuable when collaborating with team members and presenting your work. &lt;/p&gt;

&lt;p&gt;Effective technical communication will foster better understanding and lead to more successful outcomes.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>juniordeveloper</category>
      <category>coding</category>
      <category>software</category>
    </item>
    <item>
      <title>Developing and Publishing a Typescript-based SDK</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Mon, 08 May 2023 21:56:28 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/developing-and-publishing-a-typescript-based-sdk-3pph</link>
      <guid>https://forem.com/jamesoyanna/developing-and-publishing-a-typescript-based-sdk-3pph</guid>
      <description>&lt;p&gt;A Software Development Kit (SDK) is a set of development tools, libraries, documentation, and sample code that allows developers to create applications for a specific platform or system. &lt;/p&gt;

&lt;p&gt;SDKs are used to make it easier and faster for developers to build applications that interact with a particular system, by providing pre-built components and APIs that abstract away the complexity of the system.&lt;/p&gt;

&lt;p&gt;Say you want to interact with 3rd party APIs, if there was no SDK, you would have to write the HTTP client, manage authentication, do the error handling, and so on.&lt;/p&gt;

&lt;p&gt;Having an SDK provides a better developer experience and it allows the developers to use your APIs in the right way.&lt;/p&gt;

&lt;p&gt;TypeScript has gained popularity as a preferred language for building SDKs due to its strong typing and maintainability features. &lt;/p&gt;

&lt;p&gt;In this article, we will discuss how to develop a simple SDK with TypeScript. This SDK will connect to the JSON Placeholder API for fetching posts, creating and retrieving a particular post from the API. We will then also publish it on the npm registry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full code implementation can be found on this &lt;a href="https://github.com/jamesoyanna/typescript-sdk/tree/master/sdk" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our development environment:
&lt;/h3&gt;

&lt;p&gt;The first step is to set up the development environment. This involves installing Node.js and TypeScript on your computer, as well as any other dependencies that you might need. &lt;/p&gt;

&lt;p&gt;Create a folder in your computer and name it &lt;code&gt;typescript-sdk&lt;/code&gt;&lt;br&gt;
Navigate into the folder and open your command line in it.&lt;/p&gt;

&lt;p&gt;Create a new folder inside the &lt;code&gt;typescript-sdk&lt;/code&gt; folder, call it sdk. Navigate into it from the command line by typing cd sdk.&lt;/p&gt;

&lt;p&gt;Inside the sdk folder, initialize a new project using the command &lt;code&gt;npm init -y&lt;/code&gt;.&lt;br&gt;
A package.json file will automatically be created on it for you.&lt;/p&gt;

&lt;p&gt;Now let install the dependencies we will be needing for this project using this commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install microbundle&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install typescript@latest -g&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install isomorphic-unfetch&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Microbundle- Microbundle is a tool used for bundling JavaScript code into a single, self-contained file that can be used in web applications or other software projects. &lt;/p&gt;

&lt;p&gt;It is particularly useful for developing libraries or modules that need to be distributed in a standalone format.&lt;/p&gt;

&lt;p&gt;Now, lets add the necessary details to our package.json file.&lt;br&gt;
Open the package.json file and update the following&lt;/p&gt;

&lt;p&gt;Change &lt;code&gt;"main": "index.js",&lt;/code&gt; to  &lt;code&gt;"main": "dist/index.js",&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In the script section, add this script:&lt;br&gt;
&lt;code&gt;"build": "rm -rf dist &amp;amp;&amp;amp; microbundle --tsconfig tsconfig.json --no-sourcemap",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now create a &lt;code&gt;tsconfig.json&lt;/code&gt; file - You can either create it manually or by running this command:&lt;br&gt;
&lt;code&gt;tsc --init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Remove the default configuration in the &lt;code&gt;tsconfig.json&lt;/code&gt; file and add the one below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": false,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "test", "lib", "**/*spec.ts"]
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In your project folder create a new folder and name it &lt;code&gt;src&lt;/code&gt;. Create two files - &lt;code&gt;index.ts&lt;/code&gt; and &lt;code&gt;base.ts&lt;/code&gt; inside the &lt;code&gt;src&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Inside the base.ts file add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we define a Base class which is to be used as a base class for other classes that need to make API requests. &lt;/p&gt;

&lt;p&gt;The class has two private properties, &lt;code&gt;apiKey&lt;/code&gt; and &lt;code&gt;baseUrl&lt;/code&gt;, and a constructor that takes a configuration object containing an API key and an optional base URL.&lt;/p&gt;

&lt;p&gt;This Base class also has a protected method called request that makes an HTTP request to the API. The method takes an endpoint path and an optional &lt;code&gt;RequestInit&lt;/code&gt; object, which can be used to pass additional options to the fetch function.&lt;/p&gt;

&lt;p&gt;Inside the request method, the base URL and API key are used to construct the full URL for the API endpoint. &lt;/p&gt;

&lt;p&gt;A headers object is also created, which includes the API key and sets the content type to JSON.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Object.assign&lt;/code&gt; method is then used to merge the options parameter with the headers object, creating a new config object that can be passed to the fetch function.&lt;/p&gt;

&lt;p&gt;The fetch function is then called with the full URL and the config object, and the response is stored in the &lt;code&gt;response&lt;/code&gt; variable. &lt;/p&gt;

&lt;p&gt;If the response is OK (i.e. the status code is in the 200-299 range), the JSON response data is extracted using the response.json() method and returned as the requested type T. &lt;/p&gt;

&lt;p&gt;If the response is not OK, an error is thrown with the response status text as the error message.&lt;/p&gt;

&lt;p&gt;Now lets implement our post methods.&lt;/p&gt;

&lt;p&gt;Inside your &lt;code&gt;src&lt;/code&gt; folder, create another folder called posts and inside the posts folder you just created, add 2 files - index.ts and types.ts.&lt;br&gt;
Open the types.ts file and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code,we define two TypeScript types, &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;NewPost&lt;/code&gt;. &lt;br&gt;
The &lt;code&gt;Post&lt;/code&gt; type is an object with four properties: id, title, body, and userId. Each property has a specific type: id is a number, title and body are strings, and userId is also a number.&lt;/p&gt;

&lt;p&gt;The NewPost type is defined using TypeScript's Omit utility type, which takes an existing type and creates a new type by omitting one or more specified properties. &lt;/p&gt;

&lt;p&gt;In this case, we're using Omit to create a new type that's similar to Post, but with the id property omitted.&lt;br&gt;
This is useful in situations where we need to create a new object that's similar to an existing object, but with some changes. &lt;/p&gt;

&lt;p&gt;Now, in the index.ts inside the posts folder, add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in the code, we implemented the &lt;code&gt;Posts&lt;/code&gt; API and we are using Typescript to define the types of the API responses and requests.&lt;/p&gt;

&lt;p&gt;The Posts class extends the Base class and implements the methods of the Posts API. &lt;br&gt;
We added a &lt;code&gt;getPostById&lt;/code&gt; method that takes an ID and returns a single post with that ID. &lt;/p&gt;

&lt;p&gt;We also added a &lt;code&gt;getPosts&lt;/code&gt; method which returns an array of all posts. &lt;br&gt;
Then we added &lt;code&gt;createPost&lt;/code&gt; method that creates a new post by sending a POST request with the new post data as the request body. &lt;br&gt;
The API responses and requests are defined using the Post and &lt;code&gt;NewPost&lt;/code&gt; types respectively. &lt;/p&gt;

&lt;p&gt;We define constant &lt;code&gt;resourceName&lt;/code&gt; which is used as the resource name for the Posts API.&lt;/p&gt;

&lt;p&gt;Each method sends a request to the API using the request() method inherited from the Base class, passing the appropriate URL and options. &lt;br&gt;
The methods return promises that resolve to the response data, which is typed according to the method's return type definition.&lt;/p&gt;

&lt;p&gt;Now lets add mixins- Mixins are a programming concept that allows classes to inherit properties and methods from multiple sources.&lt;/p&gt;

&lt;p&gt;In other words, mixins enable the creation of a new class by combining functionality from multiple classes without having to use inheritance.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;src&lt;/code&gt; folder, create a file called utils.ts and add the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code we define a function called &lt;code&gt;applyMixins&lt;/code&gt; which is used to apply properties and methods of multiple base classes to a single derived class. &lt;/p&gt;

&lt;p&gt;The function takes two parameters, &lt;code&gt;derivedCtor&lt;/code&gt; which represents the derived class and &lt;code&gt;baseCtors&lt;/code&gt; which is an array of base classes.&lt;/p&gt;

&lt;p&gt;Inside the function, we use the forEach method to iterate over each base class in the &lt;code&gt;baseCtors&lt;/code&gt;array. &lt;/p&gt;

&lt;p&gt;We then use the &lt;code&gt;getOwnPropertyNames&lt;/code&gt; method to get all the property names of the prototype object of the base class. &lt;/p&gt;

&lt;p&gt;Then, for each property, the &lt;code&gt;defineProperty&lt;/code&gt; method is used to define a new property on the prototype object of the derived class. &lt;br&gt;
This new property has the same name and property descriptor as the corresponding property on the base class.&lt;/p&gt;

&lt;p&gt;Next, we will create a &lt;code&gt;index.ts&lt;/code&gt; file in our &lt;code&gt;src&lt;/code&gt; folder and the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here in this code, we define and exports the Typicode class as the default export of the module. &lt;br&gt;
The Typicode class extends the Base class and implements the Posts class. &lt;/p&gt;

&lt;p&gt;The Posts class provides methods to interact with the Posts API. The applyMixins function is used to add the methods and properties of the Posts class to the Typicode class. &lt;/p&gt;

&lt;p&gt;This is done using the interface keyword to declare that Typicode implements Posts and then calling applyMixins with Typicode and an array containing Posts. This allows Typicode to inherit the functionality of the Posts class and extend the functionality of the Base class.&lt;/p&gt;

&lt;p&gt;Now before we publish our sdk to npm registry, lets make some changes to our package.json file.&lt;br&gt;
Here is how  it should look like after the update.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now run &lt;code&gt;npm run build&lt;/code&gt; to build our sdk. This would generate a dist file.&lt;/p&gt;

&lt;p&gt;Now, let's publish our sdk.&lt;br&gt;
You will have to create an account on the NPM website if you haven't already done so.&lt;/p&gt;

&lt;p&gt;Log in to your NPM account from the command line in your project directory by running &lt;code&gt;npm login&lt;/code&gt; and providing your credentials.&lt;/p&gt;

&lt;p&gt;You can test your package locally using the &lt;code&gt;npm link&lt;/code&gt; command to create a symbolic link from your package to your local node_modules directory. &lt;/p&gt;

&lt;p&gt;We won't be doing any local testing here since everything appears to be functioning correctly.&lt;/p&gt;

&lt;p&gt;Run the command &lt;code&gt;npm init --scope=oyanna&lt;/code&gt;&lt;br&gt;
Ensure you replace the scope value i.e &lt;code&gt;oyanna&lt;/code&gt; with your name or any name you like before running the command.&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;npm publish --access-public&lt;/code&gt; command to publish your package to the NPM registry. &lt;br&gt;
If your publishing works fine, you should see this on your npm account:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegnt66oxowuolrbv2oh9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegnt66oxowuolrbv2oh9.PNG" alt="npm-package"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How to use the SDK:
&lt;/h3&gt;

&lt;p&gt;To use this SDK,create a folder called &lt;code&gt;sdk-test&lt;/code&gt;&lt;br&gt;
Inside the folder, initialize a new project by running &lt;code&gt;npm init -y&lt;/code&gt; in the directory or folder you have just created. This would generate a &lt;code&gt;pakage.json&lt;/code&gt; file in it.&lt;/p&gt;

&lt;p&gt;Create a tsconfig.json file inside the folder and add the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Install the SDK package we have published by running the command:&lt;br&gt;
&lt;code&gt;npm install @oyanna/typescript-sdk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a new folder inside your project directory and add a new file called &lt;code&gt;run.ts&lt;/code&gt;&lt;br&gt;
Add the following code the the file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we imported the &lt;code&gt;Typicode&lt;/code&gt; class from our SK.&lt;/p&gt;

&lt;p&gt;We then created a new instance of the &lt;code&gt;Typicode&lt;/code&gt; is with an object that contains an API key as the property. We assigned this instance to a variable called &lt;code&gt;client&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make use of the API to get post from the &lt;code&gt;jsonplaceholder&lt;/code&gt; api, we called the &lt;code&gt;getPosts&lt;/code&gt; method on the client object, which retrieves a list of posts from the Typicode API. &lt;/p&gt;

&lt;p&gt;The result is a Promise which, when resolved, and logs the retrieved posts to the console.&lt;/p&gt;

&lt;p&gt;To run the project and see the result in the console, add the following script to your package.json file. &lt;br&gt;
&lt;code&gt;&lt;br&gt;
  "scripts": {&lt;br&gt;
    "build": "tsc"&lt;br&gt;
  },&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now lets also make use of our SDK to create a post&lt;br&gt;
 Run the following command:&lt;br&gt;
&lt;code&gt;npm run build&lt;/code&gt; . This command will build your SDK by creating a dist folder&lt;br&gt;
Now run the command &lt;code&gt;tsc&lt;/code&gt;&lt;br&gt;
Then run the command: node run.js&lt;/p&gt;

&lt;p&gt;You should see the following result log into command line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpu5hcr0mok4y9ok6lig1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpu5hcr0mok4y9ok6lig1.PNG" alt="SDK-rest-result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createPost&lt;/code&gt; method is called on the client object with a new post object that contains a title, body, and user ID. &lt;/p&gt;

&lt;p&gt;When the Promise returned by createPost resolves, a message is logged to the console indicating the ID of the newly created post.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>4 techniques for using TypeScript effectively to improve code quality</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Tue, 25 Apr 2023 06:58:31 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/4-techniques-for-using-typescript-effectively-to-improve-code-quality-1fp1</link>
      <guid>https://forem.com/jamesoyanna/4-techniques-for-using-typescript-effectively-to-improve-code-quality-1fp1</guid>
      <description>&lt;p&gt;TypeScript is a statically typed superset of JavaScript that offers many benefits such as type safety, better tooling support, and improved code readability. &lt;/p&gt;

&lt;p&gt;TypeScript can make your codebase more maintainable and less prone to errors if used correctly.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss 4 advanced TypeScript techniques that can help you write cleaner, more maintainable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use Advanced Types:
&lt;/h3&gt;

&lt;p&gt;TypeScript provides many advanced types that can make your code more expressive and concise. Some examples include:&lt;/p&gt;

&lt;h4&gt;
  
  
  Union Types
&lt;/h4&gt;

&lt;p&gt;Union types allow you to define a variable that can hold values of different types. For example, the following code defines a variable that can hold either a string or a number:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let address: string | number;&lt;br&gt;
address = "Lagos"&lt;br&gt;
address = 19;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we define a variable called &lt;code&gt;address&lt;/code&gt; which can hold values of either type string or number. &lt;/p&gt;

&lt;p&gt;We then assign a string value "Lagos" to the address variable. Since we have defined address as a string or number variable, this is perfectly valid.&lt;/p&gt;

&lt;p&gt;Similarly, we assign a number value 19 to the &lt;code&gt;address&lt;/code&gt; variable, which is also valid since address is defined to accept either a string or a number.&lt;/p&gt;

&lt;p&gt;This is an example of using Union Types in TypeScript to define a variable that can hold multiple types.&lt;/p&gt;

&lt;p&gt;Using Union Types can be helpful when you have a variable that can hold values of different types, and you want to enforce type safety by ensuring that only certain types of values are assigned to it.&lt;/p&gt;
&lt;h4&gt;
  
  
  Intersection Types:
&lt;/h4&gt;

&lt;p&gt;Intersection types allow you to combine multiple types into a single type. For example, the following code defines a type that has properties from both Name and Age interfaces:&lt;/p&gt;

&lt;p&gt;`interface Name {&lt;br&gt;
  name: string;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;interface Age {&lt;br&gt;
  age: number;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;type UserInfo = Name &amp;amp; Age;&lt;/p&gt;

&lt;p&gt;const info: UserInfo = {&lt;br&gt;
  name: 'james',&lt;br&gt;
  age: 28,&lt;br&gt;
};`&lt;/p&gt;

&lt;p&gt;Here we define two interfaces named &lt;code&gt;Name&lt;/code&gt; and &lt;code&gt;Age&lt;/code&gt;, and a type named &lt;code&gt;UserInfo&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Name&lt;/code&gt; interface has a single property called name of type string and the &lt;code&gt;Age&lt;/code&gt; interface also has a single property called age of type number.&lt;/p&gt;

&lt;p&gt;We then define &lt;code&gt;UserInfo&lt;/code&gt; type using the &lt;code&gt;&amp;amp;&lt;/code&gt; (intersection) operator, which means it combines the properties of both &lt;code&gt;Name&lt;/code&gt; and &lt;code&gt;Age&lt;/code&gt; interfaces. This creates a new type that has all the properties of both interfaces.&lt;/p&gt;

&lt;p&gt;The info constant is of type &lt;code&gt;UserInfo&lt;/code&gt;, which means it has to have both the name and age properties. In this case, info is an object that has a name property with the value of 'james' and an age property with the value of 28.&lt;/p&gt;
&lt;h4&gt;
  
  
  Conditional Types
&lt;/h4&gt;

&lt;p&gt;Conditional types allow you to define types that depend on other types. For example, the following code defines a type that returns a number if T is a number, and a string otherwise&lt;/p&gt;

&lt;p&gt;`type NumberOrString = T extends number ? number : string;&lt;/p&gt;

&lt;p&gt;const a: NumberOrString = 42; // a is of type number&lt;br&gt;
const b: NumberOrString = 'hello'; // b is of type string`&lt;/p&gt;

&lt;p&gt;Here, we define a generic type called &lt;code&gt;NumberOrString&lt;/code&gt;. The generic type T is used to represent the input type that will be passed to &lt;code&gt;NumberOrString&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NumberOrString&lt;/code&gt; type is defined using a conditional type that uses the extends keyword to create a type that can either be number or string depending on the type of the generic type parameter T.&lt;/p&gt;

&lt;p&gt;In this case, the conditional type is checking whether T extends number. If it does, then the resulting type is number. If it does not, then the resulting type is string.&lt;/p&gt;
&lt;h4&gt;
  
  
  Type Guards:
&lt;/h4&gt;

&lt;p&gt;Type guards allow us to narrow down the type of a variable based on a condition. For example, the following code checks whether a variable is an array:&lt;/p&gt;

&lt;p&gt;`function isArray(value: any): value is Array {&lt;br&gt;
  return Array.isArray(value);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;const arr: any = [1, 2, 3];&lt;/p&gt;

&lt;p&gt;if (isArray(arr)) {&lt;br&gt;
  // arr is now of type Array&lt;br&gt;
  console.log(arr.length);&lt;br&gt;
}`&lt;/p&gt;

&lt;p&gt;Here, we define an function &lt;code&gt;isArray&lt;/code&gt; that takes an argument value of type &lt;code&gt;any&lt;/code&gt; and returns a boolean value indicating whether value is an array or not. &lt;/p&gt;

&lt;p&gt;The return type of this function is value is Array, which means that if the function returns true, TypeScript should infer that the input value is an array of any type.&lt;/p&gt;

&lt;p&gt;The implementation of the &lt;code&gt;isArray&lt;/code&gt; function simply checks whether the input value is an array using the built-in Array.isArray method, and returns the result.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Use Interfaces and Types
&lt;/h3&gt;

&lt;p&gt;Interfaces and types are the bread and butter of TypeScript. They allow us to define custom types and enforce type safety. &lt;br&gt;
When defining types, it is important to follow some best practices:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Always use interfaces for public API signatures.
Use types for private implementation details.
Use types to define complex types or type aliases.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Here's an example of using interfaces and types:&lt;/p&gt;

&lt;p&gt;`interface IUser {&lt;br&gt;
  id: number;&lt;br&gt;
  name: string;&lt;br&gt;
  email: string;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;type UserList = Array;&lt;/p&gt;

&lt;p&gt;function getUsers(): Promise {&lt;br&gt;
  // fetch users from the server&lt;br&gt;
}`&lt;/p&gt;

&lt;p&gt;Here, we define an interface called &lt;code&gt;IUser&lt;/code&gt; with three properties: id which is a number, name which is a string, and email which is also a string. &lt;br&gt;
The interface &lt;code&gt;IUser&lt;/code&gt; defines the structure of an object representing a user.&lt;/p&gt;

&lt;p&gt;Next, we created a type alias called &lt;code&gt;UserList&lt;/code&gt; which is an array of &lt;code&gt;IUser&lt;/code&gt; objects. This type is used to define the expected return type of the &lt;code&gt;getUsers&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;getUsers&lt;/code&gt; function is defined as an asynchronous function that returns a Promise of type &lt;code&gt;UserList&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Use Enums:
&lt;/h4&gt;

&lt;p&gt;Enums allow you to define a set of named constants. They can be used to make your code more expressive and self-documenting. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum LogLevel {
  Debug,
  Info,
  Error,
}

function log(level: LogLevel, message: string) {
  console.log(`[${LogLevel[level]}] ${message}`);
}

log(LogLevel.Info, 'Hello, world!');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we define an &lt;code&gt;enum&lt;/code&gt; called &lt;code&gt;LogLevel&lt;/code&gt;. &lt;code&gt;enum&lt;/code&gt; help us to define a set of named constants.&lt;/p&gt;

&lt;p&gt;In this case, &lt;code&gt;LogLevel&lt;/code&gt; has three constants: &lt;code&gt;Debug, Info, and Error&lt;/code&gt;. By default, the values of these constants start at 0 and increment by 1, but we can explicitly set the values if needed. &lt;/p&gt;

&lt;p&gt;In this case, Debug has a value of 0, Info has a value of 1, and Error has a value of 2.&lt;/p&gt;

&lt;p&gt;We then define a function called &lt;code&gt;log&lt;/code&gt; that takes two parameters: &lt;code&gt;level&lt;/code&gt;, which is of type &lt;code&gt;LogLevel&lt;/code&gt;, and &lt;code&gt;message&lt;/code&gt;, which is a string. &lt;br&gt;
The function logs the message to the console with a timestamp and the level of the log message.&lt;/p&gt;

&lt;p&gt;The log function is called with &lt;code&gt;LogLevel&lt;/code&gt;.Info as the level and the string 'Hello, world!' as the message. This will result in the following output in the console:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[Info] Hello, world!&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Use Decorators
&lt;/h3&gt;

&lt;p&gt;Decorators are a feature of TypeScript that allows us to modify classes and class members at runtime. They can be used to add functionality to our classes, such as logging or caching. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with args
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we define a function called &lt;code&gt;log&lt;/code&gt; that takes three parameters: &lt;code&gt;target&lt;/code&gt;, &lt;code&gt;propertyKey&lt;/code&gt;, and &lt;code&gt;descriptor&lt;/code&gt;. These parameters are part of the JavaScript/TypeScript language feature called &lt;code&gt;decorators&lt;/code&gt;, which can be used to modify or enhance the behavior of a class or its members.&lt;/p&gt;

&lt;p&gt;When this &lt;code&gt;log&lt;/code&gt; function is invoked, it first creates a variable called &lt;code&gt;originalMethod&lt;/code&gt; that holds the original value of the function that is being decorated. &lt;/p&gt;

&lt;p&gt;In other words, the &lt;code&gt;log&lt;/code&gt; function is intercepting the call to the original function, so it can modify its behavior or log additional information.&lt;/p&gt;

&lt;p&gt;Next, the descriptor.value is replaced with a new function that logs a message before invoking the original method. This new function takes an arbitrary number of arguments using the spread syntax (...args: any[]), and logs a message to the console using the console.log method.&lt;/p&gt;

&lt;p&gt;In conclusion, this article explored various advanced techniques for using TypeScript effectively to improve code readability and maintainability. &lt;/p&gt;

&lt;p&gt;We covered 4 techniques, including the use of advanced types such as Union Types, Intersection Types, Conditional Types, and Type Guards, as well as the use of Interfaces, Types, Enums, and Decorators.&lt;/p&gt;

&lt;p&gt;By leveraging these advanced TypeScript features, you can write cleaner and more expressive code, enforce type safety, and make your codebase more maintainable and less prone to errors. &lt;/p&gt;

&lt;p&gt;Additionally, by using these techniques consistently throughout your codebase, you can improve code consistency and make it easier for developers to understand and maintain your code.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Phone Book Application with Typescript and React</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Mon, 27 Mar 2023 16:52:49 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/building-a-phone-book-application-with-typescript-and-react-c2g</link>
      <guid>https://forem.com/jamesoyanna/building-a-phone-book-application-with-typescript-and-react-c2g</guid>
      <description>&lt;p&gt;A phone book is a directory used to store and organize contact information.&lt;/p&gt;

&lt;p&gt;In this article, we will be developing a phonebook application using TypeScript and React. &lt;br&gt;
TypeScript is a typed superset of JavaScript that allows us to catch errors at compile-time&lt;/p&gt;

&lt;p&gt;Our phone book application will allow users to add, edit, and delete contacts.&lt;/p&gt;

&lt;p&gt;By the end of this article, you will have a fully functional phone book application built with TypeScript and React.&lt;/p&gt;

&lt;p&gt;Here is how the final application will look  like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pqws2z2r9powvpiiuqs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pqws2z2r9powvpiiuqs.PNG" alt="Final Application" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;View &lt;a href="https://phonebook-appp.netlify.app/" rel="noopener noreferrer"&gt;Demo Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will be using &lt;code&gt;vite&lt;/code&gt; to setup our application. Vite is a build tool that is specifically designed for modern web development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Ensure that Node.js version 14.18+ is installed on your system&lt;/p&gt;

&lt;p&gt;You can download Node.js from the official website &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and npm will be installed automatically with Node.js.&lt;/p&gt;

&lt;p&gt;Firstly, navigate to the directory where you want to develop your application and scaffold your application with Vite. We can do this by running the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm create vite@latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This would ask you for the project name, framework, and variant.&lt;/p&gt;

&lt;p&gt;– For project name, you can enter phonebook&lt;/p&gt;

&lt;p&gt;– For framework, select React from the list of options&lt;/p&gt;

&lt;p&gt;– And for variant, select TypeScript.&lt;/p&gt;

&lt;p&gt;When its done, navigate into your project folder by running the command &lt;code&gt;cd phonebook&lt;/code&gt; then run the command&lt;br&gt;
&lt;code&gt;npm install&lt;/code&gt; to install all required dependencies and then  &lt;code&gt;npm run dev&lt;/code&gt; to start your application.&lt;/p&gt;

&lt;p&gt;You can open your project on Visual Studio code.&lt;br&gt;
Now let's install the dependencies we will need for this application.&lt;/p&gt;

&lt;p&gt;Open the command line or bash on your project directory and run the command:&lt;br&gt;
&lt;code&gt;npm install bootstrap@5.2.3 react-bootstrap@2.7.0 react-icons@4.7.1&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Styling the application:
&lt;/h3&gt;

&lt;p&gt;To add styling to our phonebook application, open the index.css file existing in your project folder, clear-off the existing styles and add the following content:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, you can access the main.tsx file in your project folder and place the import statement for the bootstrap CSS before the import statement for index.css, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Inside your &lt;code&gt;src&lt;/code&gt; folder, create a new folder. Name it &lt;code&gt;components&lt;/code&gt;. Create a new file, call it &lt;code&gt;Header.tsx&lt;/code&gt; and add the following content to it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Here, we import the "FC" (Functional Component) type from the 'react'. &lt;/p&gt;

&lt;p&gt;We then define the &lt;code&gt;Header&lt;/code&gt; component as a function component. The ": FC" part after "Header" specifies that the component is of type "FC", which is a shorthand for &lt;code&gt;"React.FunctionComponent"&lt;/code&gt;. This type is used to indicate that the component is a function that returns &lt;code&gt;JSX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The function itself returns a JSX element, which in this case is a header element with an h1 element inside it.&lt;br&gt;
You can now test the application by run this command &lt;code&gt;npm run dev&lt;/code&gt;.&lt;br&gt;
If every thing works fine, you should see this page display on your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w248hwekbzl6uhrje8f.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w248hwekbzl6uhrje8f.PNG" alt="Image description" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's create the form that would enable us to take input from users.&lt;/p&gt;

&lt;p&gt;Create a new file in the &lt;code&gt;components&lt;/code&gt;. Name it &lt;code&gt;ContactForm.tsx&lt;/code&gt; and add the following code to it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we  import several items from the 'react' and 'react-bootstrap' packages:&lt;/p&gt;

&lt;p&gt;We defined the component as a functional component, using the FC type from React. The function is named ContactForm.&lt;/p&gt;

&lt;p&gt;We are using the &lt;code&gt;useState&lt;/code&gt; hook to initialize a piece of state called &lt;code&gt;contact&lt;/code&gt;, which is an object that contains the values of our form fields. Initially, all of the fields are empty strings.&lt;/p&gt;

&lt;p&gt;We then define an event handler function called &lt;code&gt;handleOnChange&lt;/code&gt; that will be called whenever the user types something into one of the form fields. &lt;/p&gt;

&lt;p&gt;This function uses destructuring to get the name and value properties of the target object, which is the input element that triggered the event. &lt;/p&gt;

&lt;p&gt;It then uses the &lt;code&gt;setContact&lt;/code&gt; function to update the contact state, by returning a new object that has the same properties as the previous contact object, but with the name property set to the new value.&lt;/p&gt;

&lt;p&gt;We defined another event handler function called &lt;code&gt;handleOnSubmit&lt;/code&gt; that will be called when the user submits the form. &lt;/p&gt;

&lt;p&gt;This function prevents the default form submission behavior (which would cause a page refresh) and logs the contact object to the console. &lt;br&gt;
We have not implemented the logic for submitting the form yet.&lt;/p&gt;

&lt;p&gt;We returned a &lt;code&gt;Form&lt;/code&gt; element from the react-bootstrap package. The &lt;code&gt;onSubmit&lt;/code&gt; prop is set to the &lt;code&gt;handleOnSubmit&lt;/code&gt; function, so that it will be called when the form is submitted. The form also has a &lt;code&gt;className&lt;/code&gt; of "contact-form".&lt;/p&gt;

&lt;p&gt;The component returns several Form.Group elements from the react-bootstrap package. Each Form.Group represents a form field, with a controlId prop that uniquely identifies it. &lt;/p&gt;

&lt;p&gt;The Form.Control element within each Form.Group represents the actual input field, with props for name, value, type, placeholder, and onChange.&lt;/p&gt;

&lt;p&gt;The component also returns a &lt;code&gt;Button&lt;/code&gt; element from the react-bootstrap package, which is used to submit the form. It has a variant of "primary", a type of "submit", and a className of "submit-btn".&lt;/p&gt;

&lt;p&gt;Now, let's add our Header and &lt;code&gt;ContactForm&lt;/code&gt; component to our &lt;code&gt;App.tsx&lt;/code&gt;component.  Open the App.tsx file and import these components there. Your &lt;code&gt;App.tsx&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Checking your application on your broswer, it should now look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjcdymrykfq7krfxbr7k.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjcdymrykfq7krfxbr7k.PNG" alt="Image description" width="787" height="870"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing submitted contact information:
&lt;/h3&gt;

&lt;p&gt;Now, let's display the added  phone contacts on the page.&lt;br&gt;
To properly manage and store our contacts, we will be using the &lt;code&gt;useReducer&lt;/code&gt; hook, a built-in hook in React that would enable us to manage state using a reducer function. &lt;/p&gt;
&lt;h3&gt;
  
  
  Adding types to our application:
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;src&lt;/code&gt; folder, create a file, name it &lt;code&gt;types.ts&lt;/code&gt; and add the following content to it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we have two interfaces- Contact and Action interface.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Contact&lt;/code&gt; interface defines the shape of an object that represents a contact.&lt;/p&gt;

&lt;p&gt;The Action interface defines the shape of an object that represents an action.&lt;/p&gt;

&lt;p&gt;Create a new folder inside your &lt;code&gt;src&lt;/code&gt; folder and name it &lt;code&gt;reducers&lt;/code&gt;. Create a file inside the reducers folder and name it &lt;code&gt;contactsReducer.ts&lt;/code&gt; and add the following content into it:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we firstly import the &lt;code&gt;Contact&lt;/code&gt; and &lt;code&gt;Action&lt;/code&gt; interfaces from the &lt;code&gt;types.ts&lt;/code&gt; file &lt;/p&gt;

&lt;p&gt;We then define an interface called &lt;code&gt;AppState&lt;/code&gt; which has a single property, contacts, which is an array of Contact objects. This represents the state of the application that this reducer manages.&lt;/p&gt;

&lt;p&gt;We define and export the function &lt;code&gt;contactsReducer&lt;/code&gt; which takes two arguments: state and action. &lt;/p&gt;

&lt;p&gt;The state argument represents the current state of the application, while the action argument represents an action that has been dispatched to update the state. &lt;/p&gt;

&lt;p&gt;The return value of this function is the new state of the application.&lt;/p&gt;

&lt;p&gt;We use a switch statement to check the type property of the action argument to determine what action is being performed. &lt;/p&gt;

&lt;p&gt;In this case, the type property is expected to be a string that matches the value "ADD_CONTACT", which will be defined later.&lt;/p&gt;

&lt;p&gt;We returned a new object that represents the new state of the application. &lt;/p&gt;

&lt;p&gt;It copies all the properties of the previous state using the spread operator ...state, and then updates the contacts property with a new array that includes all the previous contacts (...state.contacts) plus the new contact that was passed in the action.payload property.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;default: return state;&lt;/code&gt;: This default case returns the current state unchanged if the action type is not recognized.&lt;/p&gt;

&lt;p&gt;In order to use the &lt;code&gt;contactsReducer&lt;/code&gt;, let's import it into App.tsx.&lt;br&gt;
Now, open the App.tsx file and update the code inside to this one below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;const initialState: AppState = { contacts: [] };&lt;/code&gt;. In this line we define the initial state for the&lt;code&gt;contactsReducer&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;const [state, dispatch] = useReducer(contactsReducer, initialState);&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;In this line of code we use the &lt;code&gt;useReducer&lt;/code&gt; hook from React to create a state management system for the App component.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt; takes two arguments: the first argument is a reducer function, and the second argument is the initial state. &lt;/p&gt;

&lt;p&gt;In this case, the &lt;code&gt;contactsReducer&lt;/code&gt; function is used as the reducer, and the &lt;code&gt;initialState&lt;/code&gt; object is passed as the initial state. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt; returns an array with two elements: the current state (state) and a dispatch function that can be used to dispatch actions to update the state. &lt;/p&gt;

&lt;p&gt;The state variable is used to store the current state of the component, while dispatch is a function that can be used to update the state by dispatching actions to the &lt;code&gt;contactsReducer&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ContactForm dispatch={dispatch} /&amp;gt;&lt;/code&gt;&lt;br&gt;
Here, We pass the dispatch function as a prop to the &lt;code&gt;ContactForm&lt;/code&gt;component so we can dispatch the action to add a contact to the contacts array.&lt;/p&gt;

&lt;p&gt;You will get a Typescript error highlighted at &lt;code&gt;dispatch&lt;/code&gt;. This is because when we pass any prop to the ContactForm  component, we need to state the type of the &lt;code&gt;dispatch&lt;/code&gt; prop in the component props list.&lt;/p&gt;

&lt;p&gt;In order to specify the dispatch prop type, you can declare an interface named &lt;code&gt;ContactFormProps&lt;/code&gt; above the component declaration in the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Add this code to your ContactForm.tsx file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ContactFormProps {
  dispatch: React.Dispatch&amp;lt;Action&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We use it inside the angle brackets after : FC.&lt;/p&gt;

&lt;p&gt;Now, we use the dispatch prop like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const ContactForm: FC&amp;lt;ContactFormProps&amp;gt; = (props) =&amp;gt; {&lt;br&gt;
  const { dispatch } = props;&lt;br&gt;
  // ....&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also ensure you add an import for the Action type at the top of the file like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { Action } from '../types';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your updated code in the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;So what we do in the code is to indicate that the &lt;code&gt;ContactForm&lt;/code&gt;component will receive a prop with the name &lt;code&gt;dispatch&lt;/code&gt; whose type is React.Dispatch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the logic to submit our form:
&lt;/h3&gt;

&lt;p&gt;inside the &lt;code&gt;handleOnSubmit&lt;/code&gt; method in &lt;code&gt;ContactForm.tsx&lt;/code&gt; file, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 dispatch({
      type: 'ADD_CONTACT',
      payload: contact
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we dispatch an action to the Redux store using the dispatch() function. &lt;br&gt;
The action is an object with a type property set to the string 'ADD_CONTACT' and a payload property set to the variable contact.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;ContactForm.tsx&lt;/code&gt; file will look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding the contact List Page:
&lt;/h3&gt;

&lt;p&gt;Now, we want to display all the contacts we will be adding using the form.&lt;br&gt;
Let's create a Page to handle that.&lt;br&gt;
Inside your components folder, create a file, call it &lt;code&gt;ContactList.tsx&lt;/code&gt; and add the following content.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, the &lt;code&gt;ContactList&lt;/code&gt; component takes in an object with a contacts property of type Contact&lt;a href="https://dev.toan%20array%20of%20Contact%20objects"&gt;&lt;/a&gt; as its props. The component then renders a table that displays the contacts in the contacts prop.&lt;/p&gt;

&lt;p&gt;The component returns a JSX that renders the contacts array as a table. It maps over the array and renders a table row for each Contact object, displaying their firstName, lastName, phoneNumber and address properties in separate columns.&lt;/p&gt;

&lt;p&gt;We can now display the &lt;code&gt;ContactList&lt;/code&gt; component in the &lt;code&gt;App.tsx&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Import the &lt;code&gt;ContactList.tsx&lt;/code&gt; file into the App.tsx file and add it below the ContactForm component.&lt;/p&gt;

&lt;p&gt;Your App.tsx file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we added a conditional statement that renders the &lt;code&gt;ContactList&lt;/code&gt; component if the contacts array in the state has any items in it. If the array is empty, the &lt;code&gt;ContactList&lt;/code&gt;component will not be rendered.&lt;/p&gt;

&lt;p&gt;If you check your browser console, you will see a warning in the console as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l3vflgrxtkr9bklt2oq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l3vflgrxtkr9bklt2oq.PNG" alt="Image description" width="447" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This warning message is indicating that each child element of the list returned by the map function in &lt;code&gt;ContactList&lt;/code&gt;should have a unique "key" prop.&lt;/p&gt;

&lt;p&gt;In React, when rendering a list of elements, it's important to provide a unique key for each item in the list. &lt;/p&gt;

&lt;p&gt;This allows React to efficiently update and re-render only the elements that have changed, instead of re-rendering the entire list every time the state changes.&lt;/p&gt;

&lt;p&gt;Let's fix this. &lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file, change the below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dispatch({
  type: 'ADD_CONTACT',
  payload: contact
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;to this one:
dispatch({
  type: 'ADD_CONTACT',
  payload: {
    id: Date.now(), // returns current timestamp
    ...contact
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we have added extra &lt;code&gt;id&lt;/code&gt; property to the payload&lt;/p&gt;

&lt;p&gt;Upon adding it, Typescript error will be underlined on it. Let's fix it.&lt;/p&gt;

&lt;p&gt;Open the types.ts file and add id to the Contact interface like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export interface Contact {
  id: number;
    firstName: string;
    lastName: string;
    phoneNumber: string;
    address: string;
    email: string;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now open the ContactList.tsx file and add the id as key prop to the child &lt;code&gt;tr&lt;/code&gt;elements that are returned by the map function like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{contacts.map(({ id, firstName, lastName, phoneNumber, address, email }) =&amp;gt; (
  &amp;lt;tr key={id}&amp;gt;
    &amp;lt;td&amp;gt;{firstName}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{lastName}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{phoneNumber}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{address}&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;{email}&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
))}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's do a bit of refactoring to our code. &lt;/p&gt;

&lt;p&gt;We will separate the component for displaying different information so it’s easy to re-use and test that component when required.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;ContactItem.tsx&lt;/code&gt; file inside the components folder and move the contents from the map method of the ContactList.tsx file inside it.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;ContactItem.tsx&lt;/code&gt; file will look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Then change the map method of the &lt;code&gt;ContactList.tsx&lt;/code&gt; file from the below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  contacts.map(({ id, firstName, lastName, phoneNumber, email, address }) =&amp;gt; (
    &amp;lt;tr key={id}&amp;gt;
      &amp;lt;td&amp;gt;{firstName}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{lastName}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{phoneNumber}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{email}&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;{address}&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
  ));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; {contacts.map(({ firstName, lastName, phoneNumber, address, email, id}) =&amp;gt; (
              &amp;lt;ContactItem
              key={id}
              id={id}
              firstName={firstName}
              lastName={lastName}
              phoneNumber={phoneNumber}
              email={email}
              address={address}
              /&amp;gt;
            ))}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Do ensure you import the &lt;code&gt;ContactItem&lt;/code&gt; into the &lt;code&gt;ContactList.tsx&lt;/code&gt; like this:&lt;br&gt;
&lt;code&gt;import ContactItem from './ContactItem';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let's add the ability to &lt;strong&gt;Edit&lt;/strong&gt; and &lt;strong&gt;Delete&lt;/strong&gt; a phone contact.&lt;/p&gt;

&lt;p&gt;We will add the Edit and Delete icons using the &lt;code&gt;react-icons&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;We have installed the library when we were starting the project.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;ContactList.tsx&lt;/code&gt; file, let's add two additional items for editing and deleting in the table heading like this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;thead className='contacts-list-header'&amp;gt;
            &amp;lt;tr&amp;gt;
              &amp;lt;th&amp;gt;First Name&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Last Name&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Phone&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Email Address&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Adress&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Edit&amp;lt;/th&amp;gt;
              &amp;lt;th&amp;gt;Delete&amp;lt;/th&amp;gt;
            &amp;lt;/tr&amp;gt;
          &amp;lt;/thead&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, open the &lt;code&gt;ContactItem.tsx&lt;/code&gt; file and replace it with this contents:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Here, we added this - &lt;code&gt;import { AiFillDelete, AiFillEdit } from 'react-icons/ai';&lt;/code&gt; to import the Edit and Delete icons from the react-icon library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
     &amp;lt;td&amp;gt;
        &amp;lt;AiFillEdit size={20} color='blue' className='icon' /&amp;gt;
      &amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;
        &amp;lt;AiFillDelete size={20} color='red' className='icon' /&amp;gt;
      &amp;lt;/td&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We added this code to make use of our icons in the table data.&lt;/p&gt;

&lt;p&gt;Your application should now look like this on your browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd26ds5v0v9as6k7mon0e.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd26ds5v0v9as6k7mon0e.PNG" alt="Phone-contact app" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will now implement the functionality for editing a contact.&lt;/p&gt;

&lt;p&gt;In order to show the edit modal popup, we will make use of the react-bootstrap modal component.&lt;/p&gt;

&lt;p&gt;Inside your component folder, create a file and name it &lt;code&gt;EditModal.tsx&lt;/code&gt;. &lt;br&gt;
Add the this content below inside the file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Here, we define a EditModal functional component. The component accepts &lt;code&gt;toggleModal, dataToEdit, showModal, dispatch&lt;/code&gt; props.&lt;/p&gt;

&lt;p&gt;– &lt;code&gt;toggleModal&lt;/code&gt;which is a function that will toggle the state value used to hide or show the modal&lt;/p&gt;

&lt;p&gt;– &lt;code&gt;dataToEdit&lt;/code&gt;will be an object containing contact details of the contact to be edited&lt;/p&gt;

&lt;p&gt;– &lt;code&gt;showModal&lt;/code&gt;will be a boolean value indicating whether to show or hide the modal&lt;/p&gt;

&lt;p&gt;– &lt;code&gt;dispatch&lt;/code&gt;function which will be helpful to dispatch the edit contact action &lt;/p&gt;

&lt;p&gt;The component uses the Modal component from the &lt;code&gt;react-bootstrap&lt;/code&gt; package to render a modal dialog that displays a form for editing contact information. The &lt;code&gt;ContactForm&lt;/code&gt;component is used to render the form.&lt;/p&gt;

&lt;p&gt;We also define the &lt;code&gt;EditModalProps&lt;/code&gt;interface, which describes the shape of the props object that the component receives.&lt;/p&gt;

&lt;p&gt;Right now, our &lt;code&gt;ContactForm&lt;/code&gt;component accepts only the dispatch prop so let’s add the remaining required prop in the definition of the type.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file and change the interface to the below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ContactFormProps {
  dispatch: React.Dispatch&amp;lt;Action&amp;gt;;
  dataToEdit: Contact | undefined;
  toggleModal: () =&amp;gt; void;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Don't forget to add an import for the Contact and Action at the top of the file like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { Action, Contact } from '../types';&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Now, update state object in the &lt;code&gt;ContactForm&lt;/code&gt;component to the content below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ContactForm: FC&amp;lt;ContactFormProps&amp;gt; = ({  dispatch, dataToEdit, toggleModal}) =&amp;gt; {
  const [contact, setContact] = useState({
    firstName: dataToEdit?.firstName ? dataToEdit.firstName : '',
    lastName:  dataToEdit?.lastName ? dataToEdit.lastName : '',
    phoneNumber: dataToEdit?.phoneNumber ? dataToEdit.phoneNumber : '',
    address: dataToEdit?.address ? dataToEdit.address : '',
    email:   dataToEdit?.email ? dataToEdit.email : '',
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we created a state object for the contact form, and populating its initial values based on any data that might be passed to the component for editing. &lt;/p&gt;

&lt;p&gt;If any of the fields are edited by the user, the 'setContact' function can be used to update the state and re-render the component with the new values.&lt;/p&gt;

&lt;p&gt;Update the &lt;code&gt;handleOnSubmit&lt;/code&gt;method to the below code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleOnSubmit: FormEventHandler&amp;lt;HTMLFormElement&amp;gt; = (e) =&amp;gt; {
    e.preventDefault();
    if(!dataToEdit){
      dispatch({
        type: 'ADD_CONTACT',
        payload:{
          id: Date.now(),
          ...contact,
        }

      })
    } else {
      toggleModal();
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So at application startup, the 'dataToEdit' variable will be undefined if the user has not clicked on the edit icon. If the edit icon has been clicked, 'dataToEdit' will contain the contact details to be edited.&lt;/p&gt;

&lt;p&gt;To handle this, we check if we are currently editing a contact. If we are not, we dispatch the 'ADD_CONTACT' action to add the new contact. If we are editing a contact, we simply close the modal without taking any further action at the moment.&lt;/p&gt;

&lt;p&gt;Once we have dispatched the 'ADD_CONTACT' action, we are calling the &lt;code&gt;toggleModal&lt;/code&gt; function to close the modal.&lt;/p&gt;

&lt;p&gt;Modify the code for the 'Add Contact' button as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Button variant='primary' type='submit' className='submit-btn'&amp;gt;
  Add Contact
&amp;lt;/Button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;to this code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Button variant='primary' type='submit' className='submit-btn'&amp;gt;
  {dataToEdit ? 'Update Contact' : 'Add Contact'}
&amp;lt;/Button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By default, the contact form will display the 'Add Contact' button text. If the user clicks on the edit icon, the 'dataToEdit' prop value will be set, and the modal will display the 'Update Contact' text while the user edits the contact information.&lt;/p&gt;

&lt;p&gt;Now replace the current content of the &lt;code&gt;App.tsx&lt;/code&gt; file with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Here, two additional states have been declared in the code above.&lt;/p&gt;

&lt;p&gt;The code includes two &lt;code&gt;useState&lt;/code&gt;functions. The first one controls whether the modal is visible or hidden, while the second one stores the details of the edited contact as an object.&lt;/p&gt;

&lt;p&gt;Initially, the object is undefined, but once a value is set, it is of the Contact type with properties such as id, &lt;code&gt;firstName&lt;/code&gt;, &lt;code&gt;lastName&lt;/code&gt;, and &lt;code&gt;phoneNumber&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To avoid any future TypeScript errors while using &lt;code&gt;dataToEdit&lt;/code&gt;or setDataToEdit, the type is declared in angle brackets.&lt;/p&gt;

&lt;p&gt;In the useEffect hook, the dataToEdit value is set back to undefined once the modal is closed, i.e., when the &lt;code&gt;showModal&lt;/code&gt;value is false.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;toggleModal&lt;/code&gt;function, the updater syntax of state is used to change the showModal state from true to false and vice versa. &lt;/p&gt;

&lt;p&gt;If the modal is already open because the &lt;code&gt;showModal&lt;/code&gt;value is true, calling the &lt;code&gt;toggleModal&lt;/code&gt;function will close the modal. On the other hand, if the modal is already closed, calling the &lt;code&gt;toggleModal&lt;/code&gt;function will display the modal.&lt;/p&gt;

&lt;p&gt;As you would observed in the &lt;code&gt;App.tsx&lt;/code&gt; file, &lt;code&gt;dispatch&lt;/code&gt; and &lt;code&gt;handleEdit&lt;/code&gt; are passed as props to the &lt;code&gt;ContactList&lt;/code&gt; component. Therefore, we need to accept them in the &lt;code&gt;ContactList&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;To do this, open the &lt;code&gt;ContactList.tsx&lt;/code&gt; file and replace its contents with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can observe here that, &lt;code&gt;handleEdit&lt;/code&gt; function takes id as a parameter and does not return anything. Therefore, it has been defined in the &lt;code&gt;ContactListProps&lt;/code&gt; interface as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ContactListProps {
  // ...
  handleEdit: (id: number) =&amp;gt; void;
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we extract the &lt;code&gt;handleEdit&lt;/code&gt; and dispatch as props and pass them to the &lt;code&gt;ContactItem&lt;/code&gt; component as illustrated below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;ContactItem
  key={contact.id}
  {...contact}
  handleEdit={handleEdit}
  dispatch={dispatch}
  /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, open the &lt;code&gt;ContactItem.tsx&lt;/code&gt; file and replace it with the following content:&lt;br&gt;
 &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Earlier, the ContactItem component was solely receiving attributes from the Contact interface.&lt;/p&gt;

&lt;p&gt;we are now also providing the &lt;code&gt;handleEdit&lt;/code&gt; and dispatch props, and thus, we have defined another interface as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ExtraProps {
  handleEdit: (id: number) =&amp;gt; void;
  dispatch: React.Dispatch&amp;lt;Action&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Upon reviewing the application, it can be observed that the modal displays the contact information of the selected contact being edited, as depicted below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n4lo7ax9tvyqfuf0r25.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n4lo7ax9tvyqfuf0r25.PNG" alt="Application displaying modal" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing Edit functionality:
&lt;/h3&gt;

&lt;p&gt;We currently have the user interface to edit and delete. Our next step is to include the code that will enable these functionalities. &lt;/p&gt;

&lt;p&gt;To achieve this, you should access the &lt;code&gt;contactsReducer.ts&lt;/code&gt; file and append a switch case for the &lt;code&gt;UPDATE_CONTACT&lt;/code&gt; action. &lt;br&gt;
Your contactsReducer.ts file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Here, The id of the contact and the updates object containing the new data are being sent for updating, as evident from the above. &lt;/p&gt;

&lt;p&gt;The contact with the matching id is being updated using the array map method. &lt;br&gt;
However, upon saving the file, a TypeScript error occurs with this case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcim6k8zbqwprrwt9zpyy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcim6k8zbqwprrwt9zpyy.PNG" alt="Upadate error" width="676" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason for the error is that the Action interface specifies the payload as a Contact object with properties including id, firstName, lastName,, address and phoneNumber.&lt;/p&gt;

&lt;p&gt;However, when handling the UPDATE_CONTACT case, we are only interested in the id and updates properties.&lt;/p&gt;

&lt;p&gt;To resolve the error, we must inform TypeScript that the payload can be either a Contact object or a type that includes id and updates properties.&lt;/p&gt;

&lt;p&gt;Now, in your types.ts file, let's add a new interface as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export interface Update {
  id: number;
  updates: Contact;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then update the Action interface to this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export interface Action {&lt;br&gt;
    type: 'ADD_CONTACT' | 'UPDATE_CONTACT'&lt;br&gt;
    payload: Contact | Update;&lt;br&gt;
  }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After this modification, payload is now a union type that can be either of Contact type or Update type, and type is a string literal type that can be either &lt;code&gt;'ADD_CONTACT'&lt;/code&gt; or &lt;code&gt;'UPDATE_CONTACT'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your types.ts file should now look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, import the new action interface into the contactsReducer.ts file&lt;/p&gt;

&lt;p&gt;However, you may encounter additional TypeScript errors in your &lt;code&gt;contactsReducer.ts&lt;/code&gt; once you make these changes. Lets see how to fix them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;So change ADD_CONTACT switch case from the below code:

case 'ADD_CONTACT':
  return {
    ...state,
    contacts: [...state.contacts, action.payload]
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;to this code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_CONTACT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Contact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this code above, we are using the as keyword for type casting, which explicitly informs TypeScript about the type of action.payload.&lt;/p&gt;

&lt;p&gt;And now change the UPDATE_CONTACT switch case from the below code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case 'UPDATE_CONTACT':
  const { id, updates } = action.payload;
    return {
      ...state,
      contacts: state.contacts.map((contact) =&amp;gt; {
        if (contact.id === id) {
          return {
            ...contact,
            ...updates
          };
        }
        return contact;
      })
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To this one:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case 'UPDATE_CONTACT':
  const { id, updates } = action.payload as Update;
    return {
      ...state,
      contacts: state.contacts.map((contact) =&amp;gt; {
        if (contact.id === id) {
          return {
            ...contact,
            ...updates
          };
        }
        return contact;
      })
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By specifying the type of action.payload as Update for the UPDATE_CONTACT case, we have resolved the TypeScript errors.&lt;/p&gt;

&lt;p&gt;With this modification, the updated &lt;code&gt;contactsReducer.ts&lt;/code&gt; file will now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;To update the contact, you need to dispatch the UPDATE_CONTACT action. You can do this by adding the following code inside the &lt;code&gt;handleOnSubmit&lt;/code&gt; method of the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file, before calling the &lt;code&gt;toggleModal&lt;/code&gt; function:&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file and inside the &lt;code&gt;handleOnSubmit&lt;/code&gt; method, in the else block, before the &lt;code&gt;toggleModal&lt;/code&gt; function call, add the below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dispatch({
  type: 'UPDATE_CONTACT',
  payload: {
    id: dataToEdit.id,
    updates: {
      id: Date.now(),
      ...contact
    }
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;And inside the if condition after the dispatch call, add the below code:&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setContact({
  firstName: '',
  lastName: '',
  phoneNumber: '',
  address: '',
  email: ''
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this code, we are resetting the form state. This ensures that when we dispatch the ADD_CONTACT action, all the user-entered data is cleared out.&lt;/p&gt;

&lt;p&gt;Now, if you check the application, you will notice that the contact can be edited successfully.&lt;/p&gt;

&lt;p&gt;Upon adding the code in your handleSubmit, your final &lt;code&gt;ContactForm.tsx&lt;/code&gt; file should now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing Delete Contact Functionality:
&lt;/h3&gt;

&lt;p&gt;Let us proceed with the addition of the delete contact feature by opening the &lt;code&gt;contactsReducer.ts&lt;/code&gt; file and including a switch case for the DELETE_CONTACT action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
case 'DELETE_CONTACT': {
    const { id } = action.payload;
    return {
      ...state,
      contacts: state.contacts.filter((contact) =&amp;gt; contact.id !== id)
    };
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To remove a contact, we include only its id in the payload property and apply the array filter method to eliminate the corresponding contact&lt;/p&gt;

&lt;p&gt;Now, in the types.ts file, change the Action interface to the following code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface Action {
  type: 'ADD_CONTACT' | 'UPDATE_CONTACT' | 'DELETE_CONTACT'
  payload: Contact | Update;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, we have included DELETE_CONTACT as an additional type.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;ContactItem.tsx&lt;/code&gt; file and, within the Delete icon, add an onClick attribute, an event handler that would be triggered when a user clicks on the delete button.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   &amp;lt;AiFillDelete size={20}     onClick={() =&amp;gt; {
            const confirmDelete = window.confirm(
              `Are you sure you want to delete contact for user ${firstName} ${lastName}?`
            );
            if (confirmDelete) {
              // dispatch action
            }
          }} color='red' className='icon' /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here have added a function to display a confirmation dialog box asking the user if they want to delete the contact for the user whose first name and last name are stored in the &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt; variables.&lt;/p&gt;

&lt;p&gt;If the user confirms the delete action, the dispatch function is called to send an action to the store. &lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;ContactItem.tsx&lt;/code&gt; file should now look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;However, upon saving the file, a TypeScript error will appear, which is demonstrated below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihw7su6y9kdgz6c2bch2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fihw7su6y9kdgz6c2bch2.PNG" alt="Delete Error" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason for the error is that the Action interface in the &lt;code&gt;contactsReducer.ts&lt;/code&gt; file specifies that the payload can be either a Contact or Update, but for the DELETE_CONTACT action, we're only passing an object with an ID inside it and we're missing the 'updates' property.&lt;/p&gt;

&lt;p&gt;To resolve this issue, you'll need to modify the Update interface in the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export interface Update {&lt;br&gt;
  id: number;&lt;br&gt;
  updates: Contact;&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
to this code:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
export interface Update {&lt;br&gt;
  id: number;&lt;br&gt;
  updates?: Contact;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this instance, we've added a question mark symbol to the 'updates' property to make it optional. This resolves the TypeScript error, as we're providing the 'id' property and the 'updates' property can be disregarded.&lt;/p&gt;

&lt;p&gt;By making this adjustment, the error in the &lt;code&gt;ContactItem.tsx&lt;/code&gt; file will disappear.&lt;/p&gt;

&lt;p&gt;If you check the application now, you'll notice that the delete contact feature is functioning correctly&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing Validations in our form
&lt;/h3&gt;

&lt;p&gt;At this point, the application's CRUD (Create, Read, Update, and Delete) functionality is complete.&lt;/p&gt;

&lt;p&gt;However, we still need to implement validation for adding or modifying contacts.&lt;/p&gt;

&lt;p&gt;To achieve this, begin by creating a new state within the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;const [errorMsg, setErrorMsg] = useState('');&lt;/p&gt;

&lt;p&gt;Here, we declare a state handle error messages&lt;/p&gt;

&lt;p&gt;Modify the handleOnSubmit method in the &lt;code&gt;ContactForm.tsx&lt;/code&gt; file to the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const handleOnSubmit = (event: React.FormEvent&amp;lt;HTMLFormElement&amp;gt;) =&amp;gt; {
    event.preventDefault();
    const {firstName, lastName, phoneNumber, address, email} = contact;
    if (
      firstName.trim() === '' ||
      lastName.trim() === '' ||
      phoneNumber.trim() === ''||
      address.trim() === ''||
      email.trim() === ''
    ) {
      setErrorMessage('All the fields are required.');
      return;
     } else if (phoneNumber.length &amp;lt; 3) {
      setErrorMessage('Please enter a phone number with more than 3 numbers.');
      return;
    }
    if (!dataToEdit) {
      dispatch({
        type: 'ADD_CONTACT',
        payload: {
          id: Date.now(),
          ...contact
        }
      });
      setContact({
        firstName: '',
        lastName: '',
        phoneNumber: '',
        address: '',
        email: '',
      });
      setErrorMessage('');
    } else {
      dispatch({
        type: 'UPDATE_CONTACT',
        payload: {
          id: dataToEdit.id,
          updates: {
            id: Date.now(),
            ...contact
          }
        }
      });
      toggleModal();
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this &lt;code&gt;handleSubmit&lt;/code&gt; function, extracts the firstName, lastName, and phoneNumber, address, email properties from the contact state.&lt;/p&gt;

&lt;p&gt;We then checks if these properties are empty or contain only whitespace, and if so, we set an error message with setErrorMessage and return from it.&lt;/p&gt;

&lt;p&gt;If the phone number is not up to 3 numbers, it sets a different error message and returns from the function.&lt;/p&gt;

&lt;p&gt;Now, we will display the error message on the screen. To do this, add the following code inside the Form tag and before the Form.Group tag while returning the JSX:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{errorMsg &amp;amp;&amp;amp; &amp;lt;p className='errorMsg'&amp;gt;{errorMsg}&amp;lt;/p&amp;gt;}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your entire ContactForm.tsx files hould now look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;With these modifications, we have successfully completed building our Phone Book application using React + TypeScript.&lt;/p&gt;

&lt;p&gt;The source-code for this project can be found &lt;a href="https://github.com/jamesoyanna/phone-book-app" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a full-stack Task Management App with Typescript,React,Nodejs part 1</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Sat, 18 Mar 2023 12:45:54 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-29in</link>
      <guid>https://forem.com/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-29in</guid>
      <description>&lt;p&gt;Task management applications are great tools to organize tasks, manage projects, and stay on top of deadlines. &lt;/p&gt;

&lt;p&gt;In this tutorial, we will be developing a Full-stack Task Manager Application using Typescript, Node.js, MongoDB, and React.&lt;/p&gt;

&lt;p&gt;Here is how the final application will look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbntxrja7xe4jfusyq62.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbntxrja7xe4jfusyq62.PNG" alt="Task Manager"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full source code of the completed of this application can be found here &lt;a href="https://github.com/jamesoyanna/task-manager" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will start by building the backend of the application using Node.js, Typescript and MongoDB.&lt;/p&gt;

&lt;p&gt;Node.js is a popular backend JavaScript runtime that allows us to build scalable and performant applications. MongoDB is a NoSQL database that is ideal for building scalable, high-performance applications with a flexible data model.&lt;/p&gt;

&lt;p&gt;In the part 2 of this post, we will then build the frontend using React, a popular JavaScript library for building user interfaces and Typescript, an open-source programming language that adds optional static typing to JavaScript. &lt;br&gt;
React allows us to build complex and interactive user interfaces with ease.Read the part 2 &lt;a href="https://dev.to/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-part-2-2ji0"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application will have features like adding, updating, and deleting tasks. We will use RESTful API endpoints to communicate between the backend and frontend.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up the Environment:
&lt;/h3&gt;

&lt;p&gt;To get started with building the Full-stack Task Manager App, you'll need to have Node.js and npm installed on your machine. &lt;/p&gt;

&lt;p&gt;You can download Node.js from the official website at &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;https://nodejs.org&lt;/a&gt;, and npm will be installed automatically with Node.js.&lt;/p&gt;

&lt;p&gt;You will also need to install MongoDB.  Download and install the latest version of MongoDB from the official website &lt;a href="https://www.mongodb.com/try/download/community" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Alternatively, you can also use a cloud-based MongoDB service like MongoDB Atlas.&lt;/p&gt;

&lt;p&gt;Install Typescript. If you don't have Typescript already install, you can run the following command to install it globally on your system.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g typescript&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Initialize the project by opening the terminal and create a new directory for the project. Name it &lt;code&gt;task-manager&lt;/code&gt;. &lt;br&gt;
Navigate to the directory and run the following command to initialize the project:&lt;br&gt;
&lt;code&gt;npm init -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a package.json file that will store the project configuration.&lt;/p&gt;

&lt;p&gt;Your package.json should look like this. We will update this later on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8db1jpvjx3lkbfgxb81s.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8db1jpvjx3lkbfgxb81s.PNG" alt="packagejson file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's install some of the dependencies we will need for this project.&lt;/p&gt;
&lt;h3&gt;
  
  
  Set up TypeScript configuration:
&lt;/h3&gt;

&lt;p&gt;Create a new file in your project directory called &lt;code&gt;tsconfig.json&lt;/code&gt; and add the following contents:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This file specifies the configuration options for the TypeScript compiler. Here, we are telling the compiler to target ES6, use CommonJS modules, output the compiled JavaScript files to a dist folder, and use the src folder as the root directory for our TypeScript files. We also set &lt;code&gt;esModuleInterop&lt;/code&gt; to true to enable interoperability between CommonJS and ES modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing required packages:
&lt;/h3&gt;

&lt;p&gt;Now let's install the required packages for your project using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install express @types/express typescript nodemon mongoose cors @types/mongoose @types/dotenv @types/cors&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, we are installing the express package for building our Node.js server and handling HTTP requests. &lt;br&gt;
We are also installing the TypeScript types for these packages using the @types prefix. We are also installing mongoose, a Object-Document Mapping (ODM) library for Node.js and MongoDB, Nodemon, helps to automatically restart our server.&lt;/p&gt;

&lt;p&gt;Now, create a new folder called &lt;code&gt;src&lt;/code&gt; in your project directory to store your TypeScript files.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src&lt;/code&gt; folder, create a file called app.ts and add the following contents:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here we have just built a simple Node.js server with Express and TypeScript. &lt;br&gt;
We import the express package and the&lt;code&gt;Express&lt;/code&gt; type from the express package. The Express type is used to define the type of the app variable, which is an instance of the express application.&lt;/p&gt;

&lt;p&gt;Next, we create a new instance of the express application by calling the express function and assigning the returned value to the app variable.&lt;/p&gt;

&lt;p&gt;We then use the &lt;code&gt;app.use&lt;/code&gt; method to add the &lt;code&gt;express.json&lt;/code&gt; middleware to our application. This middleware parses incoming requests with JSON payloads and makes the parsed data available on the req.body property.&lt;/p&gt;

&lt;p&gt;We then define the &lt;code&gt;PORT&lt;/code&gt; variable to hold the port number on which our server will listen.&lt;/p&gt;

&lt;p&gt;Finally, we call the &lt;code&gt;app.listen&lt;/code&gt; method to start the server and listen on the specified PORT. The console.log statement is used to log a message to the console indicating that the server is listening on the specified port.&lt;/p&gt;

&lt;p&gt;To run our server, let install concurrently, a tool for running both the server and client processes at the same time (this is optional. You can decide to run you server alone). Run this command&lt;br&gt;
&lt;code&gt;npm install concurrently&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add this code&lt;br&gt;
  &lt;code&gt;"start": "concurrently \"tsc -w\" \"nodemon dist/js/app\""&lt;/code&gt;to your script area in your package.json file.&lt;/p&gt;

&lt;p&gt;Your package.json file should finally look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can now run &lt;code&gt;npm start&lt;/code&gt; to start your server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to a Database:
&lt;/h3&gt;

&lt;p&gt;Now, let's connect our server to a MongoDB database using Mongoose.&lt;br&gt;
Make sure you install and setup mongoDB locally on your computer and create a database called &lt;code&gt;task-manager&lt;/code&gt;. Learn how to set it up &lt;a href="https://medium.com/@LondonAppBrewery/how-to-download-install-mongodb-on-windows-4ee4b3493514" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will be making some changes to our &lt;code&gt;app.ts&lt;/code&gt; files by adding some code. Here is the updated app.ts file&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;import mongoose from 'mongoose';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, we added this code to import the mongoose package. &lt;br&gt;
&lt;code&gt;const uri: string  =&lt;/code&gt;mongodb://localhost:27017/task-manager`&lt;/p&gt;

&lt;p&gt;We then define a constant &lt;code&gt;uri&lt;/code&gt; that holds the connection URL for our MongoDB database. The URL here specify that the MongoDB server is running on the same machine as the Node.js server and that the name of the database is &lt;code&gt;task-manager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We are using our locally installed MongoDB instance by specifying the hostname and port number.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mongoose.connect()&lt;/code&gt; method is called, passing in the URI as an argument. This method returns a promise that resolves when the connection is successful, or rejects with an error if there is a problem connecting to the database.&lt;/p&gt;

&lt;p&gt;If the connection is successful, a message is logged to the console: 'MongoDB connected successfully...'.&lt;/p&gt;

&lt;p&gt;If there is an error connecting to the database, a message is logged to the console with the error details: &lt;em&gt;Initial Distribution API Database connection error occured - ${err}.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cors()&lt;/code&gt; middleware is added to the Express application using &lt;code&gt;app.use(cors())&lt;/code&gt;. This allows Cross-Origin Resource Sharing (CORS) for all routes.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;dotenv&lt;/code&gt; module is also imported, which loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file which we will create later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Type Interface to the application:
&lt;/h3&gt;

&lt;p&gt;To add a type interface to the task manager app, we can define a TypeScript interface for the task that includes the required properties.&lt;/p&gt;

&lt;p&gt;Create a folder called &lt;code&gt;types&lt;/code&gt; in your project directory and add a new file inside the &lt;code&gt;types&lt;/code&gt; folder. Name it &lt;code&gt;task.ts &lt;/code&gt;and add the following content:&lt;br&gt;
`&lt;br&gt;
// Import Mongoose and its types&lt;br&gt;
import { Document } from 'mongoose';&lt;/p&gt;

&lt;p&gt;export interface ITask extends Document {&lt;br&gt;
    name: string;&lt;br&gt;
    description: string;&lt;br&gt;
    status: string;&lt;br&gt;
  }&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;Here, we first import the Document interface from the mongoose package. We then define an interface called &lt;code&gt;Task&lt;/code&gt; that extends the Document interface. &lt;br&gt;
This means that our Task interface will include all the properties and methods of the Document interface, as well as the name, description, and status properties that we've defined.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; property is defined as a string, the &lt;code&gt;description&lt;/code&gt; property is defined as a string, and the &lt;code&gt;status&lt;/code&gt; property is defined as a boolean.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Models
&lt;/h3&gt;

&lt;p&gt;Create a folder called &lt;code&gt;models&lt;/code&gt; in your project directory, add in it a new file called &lt;code&gt;tasks.ts&lt;/code&gt; and the following content&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
import {ITask} from '../types/tasks';&lt;br&gt;
import {model, Schema} from 'mongoose';&lt;/p&gt;

&lt;p&gt;const taskSchema = new Schema ({&lt;br&gt;
 name:{&lt;br&gt;
    type: String,&lt;br&gt;
    required: true&lt;br&gt;
 },&lt;br&gt;
 description: {&lt;br&gt;
    type: String,&lt;br&gt;
    required: true&lt;br&gt;
 },&lt;br&gt;
 status: {&lt;br&gt;
    type: Boolean,&lt;br&gt;
    required: true&lt;br&gt;
 }&lt;br&gt;
},&lt;br&gt;
{timestamps: true}&lt;br&gt;
)&lt;br&gt;
export default model('Task', taskSchema);&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we define a Mongoose schema for the Task model, which includes the name, description, and status fields as described in the ITask interface.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
import {ITask} from '../types/tasks';&lt;/code&gt;&lt;br&gt;
Firstly, we imported the &lt;code&gt;ITask&lt;/code&gt; interface from the ../types/tasks module, which defines the type structure for our Task model.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import {model, Schema} from 'mongoose'; &lt;/code&gt;&lt;br&gt;
We import the model and Schema classes from the mongoose package, which we use to define our schema and create a Mongoose model.&lt;/p&gt;

&lt;p&gt;const taskSchema = new Schema ({ ... }, {timestamps: true});&lt;br&gt;
This creates a new Mongoose schema called taskSchema using the Schema class. &lt;br&gt;
We define the schema fields for name, description, and status, as well as the {timestamps: true} option, which adds createdAt and updatedAt fields to our documents to track when they were created and last updated.&lt;/p&gt;

&lt;p&gt;&lt;code&gt; export default model&amp;lt;ITask&amp;gt;('Task', taskSchema);&lt;/code&gt;&lt;br&gt;
We then export a new Mongoose model called Task, which we create using the model function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Controllers:
&lt;/h3&gt;

&lt;p&gt;Controllers are modules that handles HTTP requests and responses for a specific set of related routes.&lt;/p&gt;

&lt;p&gt;Create a new folder called &lt;code&gt;controllers&lt;/code&gt; in our project directory. Add another folder the in controllers folder called &lt;code&gt;tasks&lt;/code&gt; and then add an index.ts file in the &lt;code&gt;tasks&lt;/code&gt; folder to define our controller functions.&lt;/p&gt;

&lt;p&gt;Add the following content in the &lt;code&gt;index.ts&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we define and exports four functions: &lt;code&gt;getTasks, addTask, updateTask, and deleteTask&lt;/code&gt;. &lt;br&gt;
These functions serve as controllers for our task manager app. They take in two parameters: req and res, which are objects representing the HTTP request and response, respectively. &lt;/p&gt;

&lt;p&gt;These parameters have types defined by the Request and Response interfaces from the express package.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;getTasks&lt;/code&gt; function queries the database for all tasks and returns them as a JSON object in the response.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;addTask&lt;/code&gt; function extracts the necessary fields from the request body, creates a new Task document with the mongoose model, saves it to the database, and returns the new task along with all tasks in the response. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;updateTask&lt;/code&gt; function updates a task document in the database based on the ID provided in the URL parameters, and returns the updated task along with all tasks in the response. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;deleteTask&lt;/code&gt; function deletes a task document from the database based on the ID provided in the URL parameters, and returns the deleted task along with all remaining tasks in the response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Routes:
&lt;/h3&gt;

&lt;p&gt;Routes are used to define the mapping between HTTP requests and the corresponding controller functions that will handle those requests.&lt;/p&gt;

&lt;p&gt;They determine how an HTTP request is handled and responded to, and are defined using a combination of HTTP methods (e.g. GET, POST, PUT, DELETE) and URL patterns.&lt;/p&gt;

&lt;p&gt;Create a new folder called &lt;code&gt;routes&lt;/code&gt; in our project directory. add a file inside the routes folder. Name it index.ts and add the following code&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
import { Router } from 'express';&lt;br&gt;
import {getTasks, addTask, updateTask, deleteTask} from '../controllers/tasks';&lt;/p&gt;

&lt;p&gt;const router : Router =  Router();&lt;/p&gt;

&lt;p&gt;router.get('/tasks',getTasks );&lt;br&gt;
router.post('/tasks/add-task', addTask);&lt;br&gt;
router.put('/edit-task/:id', updateTask);&lt;br&gt;
router.delete('/delete-task/:id', deleteTask);&lt;/p&gt;

&lt;p&gt;export default router;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here,we import the &lt;code&gt;Router&lt;/code&gt; object from the express package. We then import the four controllers we previously created in the task controller directory.&lt;/p&gt;

&lt;p&gt;Next, we create a new router instance with Router(). We then use the router object to define the HTTP methods and endpoints for our routes. like this&lt;/p&gt;

&lt;h4&gt;
  
  
  GET /tasks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;This route calls the getTasks function when the client makes a GET request to the '/tasks' endpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  POST /tasks/add-task
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;This route calls the addTask function when the client makes a POST request to the '/tasks/add-task' endpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  PUT /edit-task/:id
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;This route calls the updateTask function when the client makes a PUT request to the '/edit-task/:id' endpoint, where :id represents the ID of the task to update.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  DELETE /delete-task/:id
&lt;/h4&gt;

&lt;p&gt;This route calls the deleteTask function when the client makes a DELETE request to the '/delete-task/:id' endpoint, where :id represents the ID of the task to delete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Postman to test our endpoints:
&lt;/h3&gt;

&lt;p&gt;Postman is a popular tool used for testing and interacting with APIs (Application Programming Interfaces). &lt;/p&gt;

&lt;p&gt;It allows you to make HTTP requests to a web server and receive responses back. Postman supports various request methods like GET, POST, PUT, DELETE, etc., and lets you view the response returned by the server.&lt;/p&gt;

&lt;p&gt;Here's how you can use Postman:&lt;/p&gt;

&lt;p&gt;Download and install Postman from the official website &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once installed, open Postman and create a new request by clicking on the "New" button in the top left corner of the window.&lt;/p&gt;

&lt;p&gt;Select the HTTP method you want to use from the dropdown menu (e.g. GET, POST, PUT, DELETE, etc.).&lt;/p&gt;

&lt;p&gt;Enter the URL of the API endpoint you want to interact with in the address bar. In this case we use &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; for our project.&lt;/p&gt;

&lt;p&gt;Click on the "Send" button to send the request to the server.&lt;br&gt;
 View the response returned by the server in the "Body" section of the response tab.&lt;/p&gt;

</description>
      <category>typscript</category>
      <category>node</category>
      <category>react</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Building a full-stack Task Management App with Typescript,React,Nodejs part 2</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Sat, 18 Mar 2023 11:38:38 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-part-2-2ji0</link>
      <guid>https://forem.com/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-part-2-2ji0</guid>
      <description>&lt;p&gt;This tutorial is the part 2 and continuation of the full-stack Task management application we are building. &lt;a href="https://dev.to/jamesoyanna/building-a-full-stack-task-management-app-with-typescriptreactnodejs-29in"&gt;Here&lt;/a&gt; is the part 1 of the tutorial.&lt;/p&gt;

&lt;p&gt;In this part, we will be building the frontend of the application using React and Typescript.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Typescript Fundamentals Part 2:</title>
      <dc:creator>James Oyanna</dc:creator>
      <pubDate>Fri, 03 Mar 2023 13:40:40 +0000</pubDate>
      <link>https://forem.com/jamesoyanna/typescript-fundamentals-part-2-38d0</link>
      <guid>https://forem.com/jamesoyanna/typescript-fundamentals-part-2-38d0</guid>
      <description>&lt;p&gt;In part 1 of this article - read &lt;a href="https://dev.to/jamesoyanna/typescript-fundamentals-part-1-12ep"&gt;here&lt;/a&gt;,  we took a look at the fundamental concepts of Typescript, including its syntax, data types, and functions.&lt;/p&gt;

&lt;p&gt;Now let's look at some conceptual aspects of types and type systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Union and Intersection Types
&lt;/h3&gt;

&lt;p&gt;Union and intersection types can conceptually be thought of as logical boolean operators (AND, OR) as they pertain to types&lt;br&gt;
Union Type is a type that can have multiple possible types. It is denoted using the | symbol.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example. Consider this piece of code below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnvjs74wsednsrkttzev.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnvjs74wsednsrkttzev.PNG" alt="Union-types" width="449" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The type Address above can be either a string or a number. When we try to set Adddress to true, we get an error of &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Error: Type 'boolean' is not assignable to type 'string | number'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s write a function that can operate on strings or numbers as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg5940cojghny576iabq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg5940cojghny576iabq.PNG" alt="Print-id" width="543" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we try to execute the function &lt;code&gt;printId&lt;/code&gt; by passing a number or a string as an argument, this will work fine. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;printId(101); // work fine&lt;br&gt;
printId("202"); // work fine&lt;br&gt;
printId(true); // throws an error&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We are going to get an error if we pass any other type other than a string or a number.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nvj2jsii2dqycznmk8p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nvj2jsii2dqycznmk8p.PNG" alt="ts-error" width="422" height="200"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Intersection type:
&lt;/h3&gt;

&lt;p&gt;An intersection type is a type that combines two or more types into a single type. It is denoted using the &amp;amp; symbol. &lt;br&gt;
Let's look at an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhqsmk888rp37661kg5t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhqsmk888rp37661kg5t.PNG" alt="Type-insection" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example above, the person type is an intersection of &lt;code&gt;name and age&lt;/code&gt;, which means that any value of type &lt;code&gt;person&lt;/code&gt; must have all the properties of name and age.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;james&lt;/code&gt; variable is of type &lt;code&gt;person&lt;/code&gt; and has all the required properties, so it is allowed. However, the &lt;code&gt;kola&lt;/code&gt; variable does not.&lt;/p&gt;
&lt;h3&gt;
  
  
  Interfaces and Type Aliases
&lt;/h3&gt;

&lt;p&gt;Typescript provides two mechanisms for centrally defining types and giving them useful and meaningful names: interfaces and type aliases. &lt;/p&gt;

&lt;p&gt;We will study both concepts in depth, and explain when it makes sense to use each type. &lt;br&gt;
Interfaces and type aliases are both used to define custom types that can be used throughout our codebase. &lt;/p&gt;
&lt;h3&gt;
  
  
  Type aliases:
&lt;/h3&gt;

&lt;p&gt;Consider this piece of code: &lt;code&gt;{name: string, email: string}&lt;/code&gt;. It's a syntax we’ve used before for type annotations. &lt;/p&gt;

&lt;p&gt;This syntax will get increasingly complicated as more properties are added to this type. &lt;/p&gt;

&lt;p&gt;Furthermore, if we pass objects of this type around through various functions and variables, we will end up with a lot of types that need to be manually updated whenever we need to make any changes!&lt;/p&gt;

&lt;p&gt;Type aliases help to address this, by allowing us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;define a more meaningful name for this type&lt;/li&gt;
&lt;li&gt;declare the particulars of the type in a single place&lt;/li&gt;
&lt;li&gt;import and export this type from modules, the same as if it were an exported value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can be used to make complex types more readable or to define a type that is used in multiple places in the codebase. &lt;br&gt;
Let's take a look at this example code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyel5oalrpuvtyw6b230p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyel5oalrpuvtyw6b230p.PNG" alt="Locatiion-type" width="458" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the code above, &lt;code&gt;LocationType&lt;/code&gt; is a type alias that defines an object with a city property of type string and a &lt;code&gt;cityCode&lt;/code&gt; property of type number. The &lt;code&gt;lagos&lt;/code&gt; variable is of type &lt;code&gt;LocationType&lt;/code&gt; and has all the required properties, so it is allowed.&lt;/p&gt;

&lt;p&gt;Lets take a look at how we can use type aliases in functions;&lt;br&gt;
Consider this type alias code syntax ;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnsfj756szq1szkgqyke.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnsfj756szq1szkgqyke.PNG" alt="IUser-info" width="375" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now consider this function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function printContactInfo(info: UserContactInfo)
 { console.log(info) console.log(info.email) 
} 
const painter = { 
name: "kola ojo", 
email: "kole@gmail.com", 
favoriteColor: "Off White", 
} 
printContactInfo(painter)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code defines a function called &lt;code&gt;printContactInfo&lt;/code&gt; that takes an argument of type &lt;code&gt;UserContactInfo&lt;/code&gt;and prints it to the console. &lt;/p&gt;

&lt;p&gt;Also, we define an object called painter that has a name, email, and &lt;code&gt;favoriteColor&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Here, the&lt;code&gt;UserContactInfo&lt;/code&gt; type is a type alias that is defined at the top.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UserContactInfo&lt;/code&gt; type defines an object that has a name and email property, which is why the painter object is able to be passed as an argument to the &lt;code&gt;printContactInfo&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;printContactInfo&lt;/code&gt; function is called with the painter object as an argument, it logs the entire object to the console using console.log(info) and logs the email property using console.log(info.email). &lt;/p&gt;

&lt;p&gt;Since the painter object has an email property, both of these log statements will output the expected value to the console.&lt;/p&gt;

&lt;p&gt;This example code demonstrates how type aliases can be used to define custom types in Typescript and how they can be used to create more expressive and type-safe code. &lt;/p&gt;

&lt;p&gt;By defining a&lt;code&gt;UserContactInfo&lt;/code&gt; type alias, the code can ensure that any object passed to the &lt;code&gt;printContactInfo&lt;/code&gt; function has the required properties, which helps to catch errors early in the development process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interfaces
&lt;/h3&gt;

&lt;p&gt;An interface is a Typescript feature that allows you to define the shape of an object, including its properties and methods.&lt;br&gt;
Let's take a look at an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7obf0ft9v1fjtscc1ps.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7obf0ft9v1fjtscc1ps.PNG" alt="types-interfaces" width="380" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here in the code above, &lt;code&gt;Person&lt;/code&gt; is an interface that defines an object with a name property of type string and an age property of type number.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;james&lt;/code&gt; variable is of type Person and has all the required properties, so it this work fine.&lt;/p&gt;

&lt;p&gt;Lets take a look at another example;&lt;br&gt;
consider the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
interface Userinfo {
  name: string;
  email: string;
}
function printUserInfo(info:Userinfo){
  info.name

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define an interface called &lt;code&gt;UserInfo&lt;/code&gt; with two properties: name and email, both of which are of type string.&lt;/p&gt;

&lt;p&gt;We define a function, &lt;code&gt;printUserInfo&lt;/code&gt; that takes an argument of type &lt;code&gt;UserInfo&lt;/code&gt;, and it accesses the name property of that argument using the dot notation (info.name). &lt;br&gt;
This is just how we can access an interface property in Typescript.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inheritance in interfaces
&lt;/h3&gt;

&lt;p&gt;The way JavaScript class  “inherits” behavior from a base class, is the same as what Typescript calls a heritage clause: extends&lt;/p&gt;

&lt;p&gt;Let's take a  look at an example of how we can use inheritance with classes and interfaces in Typescript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Animal {
  eat(food: string) {
    console.log(`Eating ${food}`);
  }
}

class Dog extends Animal {
  bark() {
    return "Woof";
  }
}

const d = new Dog();
d.eat("bone"); // Provide an argument to the eat method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code illustrates how classes can inherit properties and methods from other classes using the extends keyword.&lt;/p&gt;

&lt;p&gt;In the code snippet, we have two classes: Animal and Dog.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The Animal class defines an eat method, which takes a food parameter of type string. This eat method is responsible for logging a message to the console, indicating that the animal is eating the specified food.

The Dog class extends the Animal class. This means that it inherits all the properties and methods of the Animal class, including the eat method. In addition to inheriting, the Dog class also introduces its own method called bark, which returns the string "Woof."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When we create a new instance of the Dog class and assign it to the variable d, this instance inherits all the properties and methods from the Animal class, including the eat method. However, the bark method is specific to the Dog class and is not available on the Animal class.&lt;/p&gt;

&lt;p&gt;To demonstrate the code in action, we invoke the d.eat("bone") method. TypeScript recognizes that d is an instance of the Dog class, which extends Animal, and allows us to call the eat method on the d instance while providing the required food parameter, in this case, "bone."&lt;/p&gt;

&lt;p&gt;Furthermore, if we call d.bark(), TypeScript recognizes that d is an instance of Dog, which has a bark method, and it returns the string "Woof."&lt;/p&gt;

&lt;h3&gt;
  
  
  Interfaces and type Aliases, which  one to choose:
&lt;/h3&gt;

&lt;p&gt;Interfaces and type aliases are both useful tools for defining custom types in Typescript. &lt;br&gt;
Interfaces are often used to define the shape of an object, while type aliases are used to create more readable or reusable types.&lt;br&gt;
In many situations, either a type alias or an interface would be perfectly fine, &lt;/p&gt;

&lt;p&gt;however, If you need to define something other than an object type (e.g., use of the | union type operator), you must use a type alias&lt;br&gt;
If you need to define a type to use with the implements heritage term, it’s best to use an interface&lt;br&gt;
If you need to allow consumers of your types to augment them, you must use an interface.&lt;/p&gt;

</description>
      <category>welcome</category>
    </item>
  </channel>
</rss>
