How to Build a Cinema Ticket Booking Dapp with React, Solidity, and CometChat
Tags: web3, solidity, react, decentralized
Published: 2023-06-25 16:55:48


What you will be building, see the [live](https://web3-dappbnb.web.app/) [demo](https://dapp-cinemas.web.app/) at sepolia test net and the [git repo](https://github.com/Daltonic/dappCinemas).

![Dapp Cinemas](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687529999442_DC+-+BuyTicket.gif)

![Customers Live Chatting](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687530302784_DC+Chat.gif)

## Introduction

Are you a movie fan who wants to be able to book tickets to your favorite films without having to go through a third-party website? Or are you someone who is involved in the movie business and wants to build a more secure and transparent way to sell tickets? If so, then this tutorial is for you.

We will use React, Solidity, and [**CometChat**](https://try.cometchat.com/oj0s7hrm5v78) to build our dapp. React is a JavaScript library that is used to build user interfaces. Solidity is a programming language that is used to write smart contracts on the Ethereum blockchain. CometChat is a real-time communication platform that allows users to chat with each other in real time.

By the end of this tutorial, you will have learned how to:

- Build a React app
- Deploy a Solidity smart contract
- Use CometChat to add chat functionality to a DApp

So what are you waiting for? Let's get started!


## Prerequisites

You will need the following tools installed to build along with me:

- Node.js
- Yarn
- MetaMask
- React
- Solidity
- [CometChat SDK](https://try.cometchat.com/oj0s7hrm5v78)
- Tailwind CSS
    

To set up your MetaMask for this project, I recommend that you can watch the video below.


{% embed https://www.youtube.com/watch?v=qnudOwva0fM %}


I hope you enjoy this tutorial!


## Installing Dependencies

Clone the starter kit and open it in VS Code using the command below: 


    git clone https://github.com/Daltonic/tailwind_ethers_starter_kit dappCinemas
    cd dappCinemas

Next, update the package.json with the snippet below.


{% gist https://gist.github.com/Daltonic/8c673a2cdd183095152bbc1c4856c89a %}


Next, execute the command “`yarn install`" in your terminal to install the above dependencies for this project.


## Configuring CometChat SDK

To configure the [**CometChat SDK**](https://try.cometchat.com/oj0s7hrm5v78), please follow the steps provided below. Once completed, make sure to save the generated keys as environment variables for future use.

**STEP 1:**
Head to [**CometChat**](https://try.cometchat.com/daltonic) Dashboard and create an account.

![Register a new CometChat account if you do not have one](https://paper-attachments.dropboxusercontent.com/s_95E5B376EA7D56400134387A4ABCBB8612C903A22CB8FFB5FE3936C174654F13_1681309764225_Screenshot+2023-04-12+at+3.29.17+PM.png)


**STEP 2:**
Log in to the [**CometChat**](https://try.cometchat.com/daltonic) dashboard, only after registering.


![Log in to the CometChat Dashboard with your created account](https://paper-attachments.dropboxusercontent.com/s_95E5B376EA7D56400134387A4ABCBB8612C903A22CB8FFB5FE3936C174654F13_1681309812176_Screenshot+2023-04-12+at+3.30.06+PM.png)


**STEP 3:**
From the dashboard, add a new app called **Dapp****Cinemas.**


![Create a new CometChat app - Step 1](https://paper-attachments.dropboxusercontent.com/s_95E5B376EA7D56400134387A4ABCBB8612C903A22CB8FFB5FE3936C174654F13_1681310398372_Screenshot+2023-04-12+at+3.39.28+PM.png)

![Create a new CometChat app - Step 2](https://paper-attachments.dropboxusercontent.com/s_95E5B376EA7D56400134387A4ABCBB8612C903A22CB8FFB5FE3936C174654F13_1681310434828_Screenshot+2023-04-11+at+10.12.01+AM.png)


**STEP 4:**
Select the app you just created from the list.

![Select your created app](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687535400049_Screenshot+2023-06-23+at+4.48.16+PM.png)


**STEP 5:**
From the Quick Start copy the `APP_ID`, `REGION`, and `AUTH_KEY`, to your `.env` file. See the image and code snippet.

![Copy the the APP_ID, REGION, and AUTH_KEY](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687535597311_8aozRgY0.png)


Replace the `REACT_COMET_CHAT` placeholder keys with their appropriate values.


    REACT_APP_COMETCHAT_APP_ID=****************
    REACT_APP_COMETCHAT_AUTH_KEY=******************************
    REACT_APP_COMETCHAT_REGION=**

The `.env` file should be created at the root of your project.


## Configuring the Hardhat script

Navigate to the root directory of the project and open the "`hardhat.config.js`" file. Replace the existing content of the file with the provided settings.


{% gist https://gist.github.com/Daltonic/3e7cc6f846338742ed5ceb8cdb2a1107 %}


This code configures Hardhat for your project. It includes importing necessary plugins, setting up networks (with localhost as the default), specifying the Solidity compiler version, defining paths for contracts and artifacts, and setting a timeout for Mocha tests.


## The Smart Contract File

To proceed with creating the smart contract for this project, please follow these steps:


1. In the root directory of your project, create a new folder named `contracts` inside the `src` folder. This folder will hold all the smart contract files.
2. Inside the `contracts` folder, create a new file named `DappCinemas.sol`. This file will contain the code that defines the functionality of the smart contract.
3. Copy the provided code and paste it into the `DappCinemas.sol` file.
4. Save the file to ensure that the changes are applied.
    

By following these steps, you will have successfully set up the necessary directory structure and created the `DappCinemas.sol` file, which will serve as the foundation for implementing the logic of the smart contract.


{% gist https://gist.github.com/Daltonic/c4846a1350b27142a5edbbb3a44b0384 %}


Here is an overview of the key components and functions of the smart contract:


1. `**Ownable**`: The contract inherits from the `**Ownable**` contract in the OpenZeppelin library, which provides basic access control by allowing only the contract owner to execute certain functions.
    
2. `**Counters**`: The contract uses the `**Counters**` library from OpenZeppelin to keep track of the total number of movies, tickets, and time slots created.
    
3. `**MovieStruct**`: This struct defines the properties of a movie, including `**id**`, `**name**`, `**imageUrl**`, `**genre**`, `**description**`, `**timestamp**`, and `**deleted**`.
    
4. `**TicketStruct**`: This struct defines the properties of a ticket, including `**id**`, `**movieId**`, `**slotId**`, `**owner**`, `**cost**`, `**timestamp**`, `**day**`, and `**refunded**`.
    
5. `**TimeSlotStruct**`: This struct defines the properties of a time slot for a movie screening, including `**id**`, `**movieId**`, `**ticketCost**`, `**startTime**`, `**endTime**`, `**capacity**`, `**seats**`, `**deleted**`, `**completed**`, `**day**`, and `**balance**`.
    
6. `**Action**` event: This event is emitted to indicate successful actions performed within the contract.
    
7. `**balance**` variable: This variable stores the contract's current balance.
    
8. Various mappings: The contract uses mappings to store and retrieve data related to movies, time slots, and ticket holders.


**The contract provides the following functions:**

- `**addMovie**`: Allows the contract owner to add a new movie to the system by providing the necessary details such as `**name**`, `**imageUrl**`, `**genre**`, and `**description**`.
    
- `**updateMovie**`: Allows the contract owner to update the details of an existing movie by specifying the `**movieId**` and providing the updated information.
    
- `**deleteMovie**`: Allows the contract owner to delete a movie from the system by specifying the `**movieId**`. However, it can only be deleted if there are no purchased tickets associated with it.
    
- `**getMovies**`: Retrieves an array of all available movies in the system.
    
- `**getMovie**`: Retrieves the details of a specific movie by providing its `**id**`.
    
- `**addTimeslot**`: Allows the contract owner to add a time slot for a movie screening by specifying the `**movieId**` and providing arrays of `**ticketCosts**`, `**startTimes**`, `**endTimes**`, `**capacities**`, and `**viewingDays**` for the time slots.
    
- `**deleteTimeSlot**`: Allows the contract owner to delete a time slot for a movie screening by specifying the `**movieId**` and `**slotId**`. The function refunds all ticket holders for the canceled time slot.
    
- `**markTimeSlot**`: Allows the contract owner to mark a time slot as completed by specifying the `**movieId**` and `**slotId**`. The function adds the balance of the completed time slot to the contract's overall balance.
    
- `**getTimeSlotsByDay**`: Retrieves an array of time slots available for a specific day by specifying the `**day**`.
    
- `**getTimeSlot**`: Retrieves the details of a specific time slot by providing its `**slotId**`.
    
- `**getTimeSlots**`: Retrieves an array of time slots available for a specific movie by specifying the `**movieId**`.
    
- `**buyTicket**`: Allows users to purchase tickets for a movie by specifying the `**movieId**`, `**slotId**`, and the number of `**tickets**` to purchase. The function checks for availability, verifies the payment amount, and records the ticket details.
    
- `**getMovieTicketHolders**`: Retrieves an array of ticket holders for a specific movie by providing its `**movieId**`.
    
- `**getTicket**`: Retrieves the details of a specific ticket by providing its `**ticketId**`.
    
- `**refundTicket**`: Allows the contract owner to refund a ticket by specifying the `**ticketId**`. The function refunds the ticket owner and updates the ticket's `**refunded**` status.
    
- `**getContractBalance**`: Retrieves the current balance of the contract.
    
- `**withdrawBalance**`: Allows the contract owner to withdraw the contract's balance.

In a nutshell, the DappCinemas smart contract provides functionality for managing a decentralized cinema ticket booking system on the Ethereum blockchain. It allows the cinema owner to add, update, and delete movies, create time slots for screenings, and enables users to purchase tickets for specific movie screenings. The contract keeps track of movie and time slot details, ticket holders, and manages the financial transactions related to ticket sales.

Here is an opportunity to enhance your proficiency in Solidity, the web3 language. [**Get hold of your copy of a comprehensive book that will guide you towards mastery in Solidity.**](https://dappmentors.org/links/zewcyq) Access it now by following this link.


![Capturing Smart Contract Development](https://paper-attachments.dropboxusercontent.com/s_A83006EDA71414B7192208CC855F36D53EB33CBD2E6946B1117858F9736DEB77_1679056023593_0b_CDn4V.png)

## The Test Script

The test script provided below is used to test the functionality of the `**DappCinemas**` contract. It contains several test cases grouped into different sections.

In the "**Movie Management**" section, the script tests creating a movie, updating its details, and deleting a movie.

In the "**Showtime Management**" section, the script tests adding a showtime for a movie, deleting a showtime, and verifying the availability of showtimes.

In the "**Ticket Booking**" section, the script tests booking a ticket for a specific movie and showtime, calculating revenue generated by a movie, canceling a booked ticket, and withdrawing funds from the company balance.

The script uses Chai assertions for making assertions and the Hardhat framework for deploying and interacting with the contract. Before each test case, the contract is deployed, and necessary variables and initializations are performed.

At the root of the project, create a folder if not existing called “**test**”, copy and paste the code below inside of it.


{% gist https://gist.github.com/Daltonic/1873cdf797089dfd3fcb436786e174c9 %}


By running `**yarn hardhat test**` or `**npx hardhat test**` on the terminal will test out all the essential function of this smart contract

## The Deployment Script

The hardhat deployment script provided below is responsible for deploying the `**DappCinemas**` contract to the blockchain using Hardhat. 

It first obtains the contract factory using `**ethers.getContractFactory**`, deploys the contract, and waits for it to be deployed successfully. Then, it adds a movie to the deployed contract by invoking the `**addMovie**` function with the movie details. After that, it writes the contract address to a JSON file for future reference. Finally, it logs the deployed contract address to the console. 

If any errors occur during the deployment process, they are logged, and the script exits with a non-zero exit code. 

In the root of the project, create a folder called “**scripts**” and another file inside of it called “`deploy.js`” if it doesn’t yet exist. Copy and paste the code below inside of it.


{% gist https://gist.github.com/Daltonic/734d3d08b304db45e655402f60439579 %}


Next, run the commands below to deploy the smart contract into the network on a terminal.


![Activities of Deployment on the Terminal](https://paper-attachments.dropboxusercontent.com/s_95E5B376EA7D56400134387A4ABCBB8612C903A22CB8FFB5FE3936C174654F13_1681314007681_0RFvAh6Q.png)


If you require additional assistance with setting up Hardhat or deploying your Fullstack DApp, I recommend watching this informative video that provides guidance and instructions.


{% embed https://www.youtube.com/watch?v=6lIq8MCfaGE %}



## Developing the Frontend

To begin developing the frontend of our application, we will create a new directory called `components` in the “**src”** directory. This folder will contain all the components required for our project. For each of the components listed below, you need to create the corresponding files within the `src/components` folder.


## Sidebar Component
![Sidebar Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687538213386_Screenshot+2023-06-23+at+5.31.19+PM.png)


The above component represents a sidebar for application. It displays a navigation menu with options such as "Movies," "Manage movies," and "Add Movies." It also provides the functionality to connect a wallet and displays the connected account. The component is responsive and hidden on small screens.

Create this component in the components folder, copy and paste the codes below into it.


{% gist https://gist.github.com/Daltonic/f9f77e6e808e985913a48a78b240694d %}



## Header Component
![The Header Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687538561338_Screenshot+2023-06-23+at+5.42.27+PM.png)


The below code represents a header component for this application. It includes a responsive menu icon that toggles a menu when clicked. The menu contains options such as "Movies," "Manage Movie," and "Add Movie." It also includes a search bar for searching content. The component allows users to connect their wallets and displays the connected account. The menu is hidden on larger screens and displayed on smaller screens. See the codes below, ensure you copy and paste appropriately.


{% gist https://gist.github.com/Daltonic/527714502d7253bfb57af7c4bc122fc9 %}



## Banner Component
![The Banner Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687539353097_Screenshot+2023-06-23+at+5.55.38+PM.png)


The code below represents a component called `**Banner**` in this project. This component displays a banner with a background image. The banner contains a title and a subtitle rendered with specific styles. This component is designed to be responsive and has a flex layout to position the title, subtitle, and button within the banner. See the code below.


{% gist https://gist.github.com/Daltonic/e691395253f83c551d35cb5a96015673 %}



## Movie Cards Component
![The Movie Card Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687539631848_Screenshot+2023-06-23+at+6.00.19+PM.png)


The `**MovieCard**` component is a reusable component in this project that renders a movie card with an image, title, and truncated description. It is wrapped in a `**Link**` component from React Router to enable navigation to the movie's details page. The movie image, title, and description are dynamically populated using the `**movie**` prop. The component applies responsive styling and visual effects such as rounded corners, shadows, and borders. See the code below.


{% gist https://gist.github.com/Daltonic/f31f234e29b5e1e9467bc38089c47bba %}



## Movies Table and Action Components
![The Movies Table Components](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687551891799_Screenshot+2023-06-23+at+9.20.53+PM.png)


The `**MoviesTable**` component displays a table of movies with information such as image, title, genre, date added, and description. It uses utility functions to format data and includes actions like editing, deleting, and managing time slots for each movie.

The `**MovieAction**` component on the other hand renders a dropdown menu with options to edit, delete, add time slots, and view all time slots for a movie. It uses icons and React Router's `**Link**` component for visual representation and navigation.

Use the codes below.


{% gist https://gist.github.com/Daltonic/6b32c69017e0ba8e509f6779c2693e36 %}


**If you're interested in learning how to create a decentralized app by building a web3 lottery dapp, I recommend that you watch this video:**


{% embed https://www.youtube.com/watch?v=mVxRzkvX_w0 %} 


This video provides a hands-on tutorial on how to build a lottery dapp using NextJs, Tailwind CSS, and Solidity.

## Update Movie Component
![The movie update component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687552438579_Screenshot+2023-06-23+at+9.33.30+PM.png)


The `**UpdateMovie**` component is a modal that allows users to edit movie details. It includes a form with input fields for image URL, movie name, genre, and description. The form validates required fields and displays a toast notification when the update is in progress, successful, or encounters an error. The component also handles the closing of the modal, updates the movie state, and triggers the updateMovie function. Use the code below.


{% gist https://gist.github.com/Daltonic/10144a34a0e49094aa542d104cd6aa78 %}



## Delete Movie Component
![The delete movie component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687552874843_Screenshot+2023-06-23+at+9.41.02+PM.png)


The `DeleteMovie` component is a modal that confirms the deletion of a movie. It displays a warning icon and the name of the movie to be deleted. The component includes a form with a delete button. When the form is submitted, a toast notification is displayed to indicate the progress of the deletion. The component also handles the closing of the modal and triggers the deleteMovie function. Use the snippet below:


{% gist https://gist.github.com/Daltonic/32a3ae6a64382d0fd523b638b4544931 %}

## Withdrawal Component
![The Withdrawal Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687681164971_Screenshot+2023-06-25+at+9.18.55+AM.png)


The `**Withdrawal**` component is a modal form that allows users to withdraw money. It utilizes React hooks such as `**useState**` and custom hooks like `**useGlobalState**` from the store. The component interacts with the blockchain through the `**withdraw**` function from the blockchain service. Toast notifications from `**react-toastify**` are used to display the status of the transaction. The component captures input values, handles form submission, and provides a close button to dismiss the modal. Use the code below.


{% gist https://gist.github.com/Daltonic/b1ff3ba387d71d402ee707978964d39a %}



## The Chat Components
![The Chat Options](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687553247027_Screenshot+2023-06-23+at+9.46.04+PM.png)

![The Chat Modal](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687553261668_Screenshot+2023-06-23+at+9.47.01+PM.png)


The `ChatActions` component provides various chat options based on the user's authentication status and the movie's group status. It includes functionality for signing up, logging in, creating a group, and joining a group. Each action triggers an asynchronous operation and displays toast notifications to indicate the progress and outcome of the operation.

The `ChatModal` component represents a chat room modal. It displays messages exchanged in the chat room and allows the user to send new messages. The component includes functionality for fetching initial messages, listening for new messages, and scrolling to the latest message. It also includes a `Message` component that represents an individual chat message, displaying the sender's avatar and truncated username along with the message content.

The chat components, `**ChatActions**` and `**ChatModal**`, are built using the CometChat SDK from the chat service. CometChat provides a comprehensive set of features and functionalities for integrating real-time chat functionality into applications.

In the `**ChatActions**` component, functions such as `**signUpWithCometChat**`, `**loginWithCometChat**`, `**createNewGroup**`, and `**joinGroup**` are called asynchronously using the CometChat SDK. These functions handle the respective chat operations, such as signing up a user, logging in, creating a group, and joining a group. Toast notifications are used to indicate the status of these operations, such as pending, success, or error.

The `**ChatModal**` component utilizes the CometChat SDK to retrieve messages from a specific chat room (`**getMessages**`), send new messages (`**sendMessage**`), and listen for incoming messages (`**listenForMessage**`). The component also includes functionality to scroll to the latest message in the chat room.

By leveraging the CometChat SDK, these chat components enable users to interact with chat functionality, including signing up, logging in, creating or joining groups, and exchanging messages within a chat room.

[**Bring real-time messaging to your application with CometChat. Try our SDK and UI Kits today!**](https://try.cometchat.com/oj0s7hrm5v78)

Now, let’s create these components into our application like we have been doing with the other components. Use the code below.


{% gist https://gist.github.com/Daltonic/80196de5b0f62a3066ab18625ea7d5a6 %}

## The Timeslots Components
![Timeslot Table and Actions Components](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687681654964_Screenshot+2023-06-25+at+9.25.26+AM.png)


The `TimeSlotTable` component displays a table of time slots. It receives an array of `slots` as props and maps over them to generate table rows. Each row represents a time slot and displays information such as ID, day, ticket cost, balance, start time, end time, capacity, and actions. The `convertTimestampToDate` and `convertTimestampToTime` functions from the store are used to format the timestamp values. The actions column includes the `TimeslotActions` component.

The `TimeslotActions` component is a dropdown menu of actions available for each time slot. It provides options to delete a slot, mark a slot as completed, and view all ticket holders. The actions trigger corresponding functions like `handleDelete` and `handleCompletion`. The component uses icons from various libraries such as `react-icons/tfi`, `react-icons/bs`, and `react-icons/bi`. Toast notifications from `react-toastify` are used to display the status of the transaction. The menu is implemented using the `Menu` component from `@headlessui/react`, and the `Link` component is used for navigation.

Use the codes below for creating the both components.


{% gist https://gist.github.com/Daltonic/b42469f766339fac9017e80af6352b7e %}



## Timeslot Lits Component
![The Timeslot List](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687683222844_Screenshot+2023-06-25+at+9.53.21+AM.png)


The `TimeSlotList` component displays a list of available time slots, allowing users to purchase tickets. It uses the `slots` array as props to populate the list items with relevant information such as date, time, seat availability, ticket cost, and a "Buy Ticket" button. The component handles ticket purchases through the `handleTicketPurchase` function and displays transaction status using `react-toastify` notifications. The component also utilizes the `FaEthereum` icon from `react-icons/fa` and applies Tailwind CSS classes for styling.
Use the code below.


{% gist https://gist.github.com/Daltonic/0070ebffc3d1f53eb5fdf3ce63f4b29b %}

## Delete Slot Component
![The Delete Slot Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687683418796_Screenshot+2023-06-25+at+9.56.46+AM.png)


The `DeleteSlot` component displays a modal to confirm the deletion of a time slot. It manages state using `useGlobalState` and `setGlobalState`, and imports icons from `react-icons/ri` and `react-icons/fa`. The modal shows a warning, confirms the selected slot's deletion, and has a "Delete" button. Deletion is handled by `handleDelete`, using `deleteSlot` from `blockchain`. Styling is done with Tailwind CSS classes. Overall, `DeleteSlot` provides a confirmation interface for deleting slots and handles related actions and state changes.
Use the code below:


{% gist https://gist.github.com/Daltonic/400418aa3ac5eaf30d50c92eeedbc23d %}



## Ticket Holders Component
![The Ticket Holder Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687683766507_Screenshot+2023-06-25+at+10.02.37+AM.png)


The `TicketHoldersTable` component renders a table that displays ticket holders' information. It receives the `holders` and `slot` props. The table structure consists of three columns: "Id," "Cost," and "Holder." The `holders` array is mapped to generate table rows, with each row displaying the corresponding holder's information. The "Id" column displays the index of the holder plus one, the "Cost" column shows the ticket cost from the `slot` prop, and the "Holder" column displays the holder's information. The component utilizes Tailwind CSS classes for styling and provides an organized representation of the ticket holders' data. See the codes below.


{% gist https://gist.github.com/Daltonic/654f2600984057990bcaa39ad8acd5ae %}



## Find Holders Component
![The Find Ticket Holder](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687684101003_Screenshot+2023-06-25+at+10.08.10+AM.png)


Lastly for the components is the `FindHolder` component, which displays a modal window for searching ticket holders by their Ethereum address. It uses hooks and global state variables to manage the search functionality. The modal includes an input field for entering the address, and the `handleSearch` function updates the results. Matching addresses are shown along with the count. The component provides a user-friendly interface for searching ticket holders within a modal window. See the code below.


{% gist https://gist.github.com/Daltonic/c8a13266e997f11c8506b2743c600b5b %}


Want to learn how to build an NFT marketplace? Watch this video tutorial:


{% embed https://www.youtube.com/watch?v=fJIiqeevqoU %}


This video provides a step-by-step guide on how to build an NFT marketplace using React and Solidity. The video covers all of the essential concepts and techniques you need to know to build an NFT marketplace.

Now that we have covered all the components in this application, it’s time we couple the various pages together. Let’s start with the homepage.

To begin developing the pages of our application, we will create a new directory called pages in the “src” directory. This folder will contain all the pages required for our project. For each of the pages listed below, you need to create the corresponding files within the `src/pages` folder.


## The List Movies Page
![The List Movies Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687684848814_Screenshot+2023-06-25+at+10.20.35+AM.png)


The `ListMovies` page component displays a list of movies. It utilizes the `useGlobalState` hook to retrieve the movie data from the global state. The component includes a `Banner` component at the top and a grid layout for displaying the movies using the `MovieCard` component. If there are movies available, they are rendered in the grid layout. Otherwise, a message indicating that there are no movies yet is displayed. The `ListMovies` component provides a visually appealing way to present a collection of movies. Use the code below.


{% gist https://gist.github.com/Daltonic/87939c3c2bf967848511d04b9737421d %}



## Movie Details Page
![Specific Movie Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687685760780_Screenshot+2023-06-25+at+10.35.29+AM.png)


The `**MovieDetails**` page component is responsible for displaying detailed information about a specific movie. It utilizes various hooks and services to fetch and manage the movie data, time slots, and chat group (CometChat SDK). The component retrieves the movie ID from the URL parameters using `**useParams**` from React Router.

Upon rendering, the component fetches the movie details and available time slots by calling the `**getMovie**` and `**getSlots**` functions from the blockchain service. It also retrieves the chat group associated with the movie using the `**getGroup**` function. The component manages the loading state with the `**loaded**` and `**setLoaded**` state variables.

Once the data is loaded, the component displays the movie image, name, genre, description, and chat actions. It also includes the `**TimeSlotList**` component, which filters and displays the available time slots based on the `**isValidTimeslot**` function. See the code below.


{% gist https://gist.github.com/Daltonic/fa63a1551ef4496cdb286b7165ab5d09 %}



## Manage Movies Page
![The Manage Movies Component](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687686069763_Screenshot+2023-06-25+at+10.40.50+AM.png)


The `ManageMovies` page allows users to manage movies. It displays a table of movies using the `MoviesTable` component. Users can add a new movie by clicking the "Add Movie" button, which navigates them to the **"/add/movies"** route. The page also provides a "Withdraw" button that triggers a withdrawal action and displays the current balance using the `balance` state. The withdrawal action is implemented using the `setGlobalState` function and opens the withdrawal modal. The page layout is responsive and utilizes spacing and styling to enhance the user interface. See the code below.


{% gist https://gist.github.com/Daltonic/03ee69ae786425ef79fdd6db627d69e2 %}



## Add Movie Page
![The Add Movie Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687693801318_DC+-+Add+Movie.gif)


The `AddMovie` page allows users to add a new movie. It provides a form where users can input the movie's image URL, name, genre, and description. Upon submission, the `handleSubmit` function is called, which performs input validation and calls the `addMovie` function from the blockchain service to add the movie. 

The form submission process displays a toast notification to indicate the status of the transaction, including pending, success, or error messages. If all the required fields are filled, the movie is added successfully, and the user is navigated back to the home page `("/")`. 

The page layout is centered and responsive, and the form input fields are styled using Tailwind classes to ensure a consistent and user-friendly interface. See the codes below.


{% gist https://gist.github.com/Daltonic/e4d922872cd5216488f8eacda5db61cd %}



## Add Slot Page
![The Add Slot Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687693850922_DC+-+Add+Timestamp.gif)


The `AddTimeslot` page allows users to add a time slot for a movie. It uses React for building the user interface. The component includes form inputs for selecting a day, start time, end time, ticket cost, and capacity.

The selected day is stored in the `selectedDay` state variable. When a day is selected, it triggers a call to `getSlotsByDay` function to fetch existing time slots for that day.

The form is submitted when all required fields are filled, and the data is stored in separate state variables for ticket costs, start times, end times, capacities, and viewing days.
There are functions to handle form submission, saving the time slot to the blockchain, resetting the form, and removing selected slots.

The component utilizes external libraries such as `react-datepicker` for date and time picking, `react-router-dom` for navigation, and `react-toastify` for displaying transaction status. See the codes below.


{% gist https://gist.github.com/Daltonic/41895eec2f65d964aa24ae3e2f598f02 %}



## All Time slots Page
![The Timeslot Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687687200289_Screenshot+2023-06-25+at+10.59.47+AM.png)


The `**TimeSlots**` component is a page that displays the time slots for a specific movie. It retrieves the movie ID from the URL parameters using `**useParams**` and fetches the movie details and corresponding time slots from the blockchain using `**getMovie**` and `**getSlots**` functions.

The fetched movie information is stored in the `**movie**` state variable, while the time slots are stored in the `**slots**` state variable using the global state management system.
The component renders a heading displaying the movie name and a `**TimeSlotTable**` component to present the time slots in a table format.

Two links are provided: "Add Slots" redirects to a page where new time slots can be added for the movie, while "Back" navigates to the movie management page. Use the code below.


{% gist https://gist.github.com/Daltonic/67a8a0f9074ce88c3e5ada07dc0aa87f %}



## Ticket Holders Page
![The Ticket Holders Page](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687687548620_Screenshot+2023-06-25+at+11.05.38+AM.png)


Lastly, the `**TicketHolders**` component is a page that displays the ticket holders for a specific time slot of a movie. It retrieves the slot and movie details from the blockchain, renders a heading with the movie name and slot date, and presents the ticket holders in a table format. 

The component includes a "Find Holder" button to search for a specific ticket holder and a "Back" link to navigate back to the time slots page. It uses React, `**react-router-dom**`, and global state management. Use the code below.


{% gist https://gist.github.com/Daltonic/70578ed923d7ac21ed7ed141878b124b %}


Fantastic, we have so far worked on all the components and pages of this project, let’s couple them together with their respective services. Let’s start with the App component.


## App Entry File

The `**App**` component serves as the main entry point for the Dapp Cinemas project. It sets up the application's routing using `**react-router-dom**` and includes various pages and components to manage movies, time slots, ticket holders, and other functionality. 

The component also initializes the connection to the blockchain, loads blockchain data, and checks the authentication state. It renders a layout with a sidebar, header, and content area. The content area displays different pages based on the current route, such as listing movies, movie details, time slots, adding time slots, managing movies, etc. 

Additionally, it includes several auxiliary components for updating movies, deleting movies and time slots, finding ticket holders, and making withdrawals. The component also utilizes the `**react-toastify**` library for displaying toast notifications.

Replace the existing `App.jsx` component with the code below.


{% gist https://gist.github.com/Daltonic/5e245d36d30ab4415671a8bd9caff43a %}



## The Blockchain Service

The provided service is responsible for interacting with the Ethereum blockchain and managing the Dapp Cinemas smart contract. It allows the application to perform various actions such as adding movies, updating movie details, deleting movies, adding time slots, deleting time slots, buying tickets, and handling withdrawals.

The service utilizes the Ethereum provider (`**Metamask**`) to connect to the user's wallet and perform transactions using the `**ethers.js**` library. It includes helper functions for converting between Wei and Ether units and for structuring movie and timeslot data.

All the components and pages in the application leverage this service to interact with the blockchain and retrieve/update movie and timeslot information. They call the appropriate functions from this service to perform the desired actions, ensuring the application's functionality and data synchronization with the blockchain. 

To utilize this code, create a folder called “**services**” in the “**src**” directory of the project and another file called “`blockchain.js`” within this folder. Now copy and paste the code below inside of it.


{% gist https://gist.github.com/Daltonic/2da8c4638c1999ebe598b283ba60d99a %}


Please ensure that you update the environment variables to look like this:


    REACT_APP_COMETCHAT_APP_ID=****************
    REACT_APP_COMETCHAT_AUTH_KEY=******************************
    REACT_APP_COMETCHAT_REGION=**
    REACT_APP_RPC_URL=http://127.0.0.1:8545


## The Chat Service

The chat service provided uses the CometChat Pro SDK to enable chat functionality in the application. It includes functions to initialize CometChat, handle user authentication, interact with chat groups, fetch and send messages, and listen for incoming messages. 

The `**initCometChat**` function initializes CometChat with the app ID and region. User authentication is managed through the `**loginWithCometChat**` and `**signUpWithCometChat**` functions. The `**logOutWithCometChat**` function logs the user out and updates the global state. 

Group management is handled by functions such as `**createNewGroup**`, `**getGroup**`, and `**joinGroup**`. Message-related operations are performed using functions like `**getMessages**`, `**sendMessage**`, and `**listenForMessage**`. 

All components and pages in the application rely on these functions to leverage the chat service's capabilities, including user authentication, group interactions, and message handling.

Still inside the services folder, create a file named “chat.jsx”, copy and paste the code below into it.


{% gist https://gist.github.com/Daltonic/e3ca8cd85fd2a25a156d6d3787d4d415 %}


Great, now let’s work on the store file that serves as a state management library.


## The Store File

The store service provided below is responsible for managing global state in the application using the `[**react-hooks-global-state**](https://www.npmjs.com/package/react-hooks-global-state)` library. It includes functions and variables for setting, retrieving, and using global state values. The initial global state includes properties such as `**movies**`, `**messages**`, `**balance**`, `**currentSlots**`, `**ticketHolders**`, and more.

Additionally, the service provides utility functions like `**truncate**` to truncate text based on a specified length, `**convertTimestampToDate**` to convert a timestamp to a formatted date, and `**convertTimestampToTime**` to convert a timestamp to a formatted time.

The functions `**setGlobalState**` and `**useGlobalState**` are used to set and access global state values, respectively, while `**getGlobalState**` retrieves the current global state.

The components and pages in the application leverage this store service to manage and share data across different parts of the application, ensuring synchronized state management and access to shared data.

Create a folder called “**store**” in the “**src**” directory of this project and another file called “`**index.jsx**`” inside of it. Now copy and paste the code below inside of it.


{% gist https://gist.github.com/Daltonic/7e65c3f4cf45f883979b089e6b531ff8 %}



## The Index file

The `**index.jsx**` file serves as the entry point of the application. It initializes the CometChat service, sets up dependencies, and renders the React application using the `**App**` component within a `**BrowserRouter**`. It creates a root element for rendering and sets up the necessary configurations for the application to start running.

Replace the code below inside of the “`**index.jsx**`” file in the src folder of this project.


{% gist https://gist.github.com/Daltonic/9f9af78c902b98c9cd1f0f075cba4fb9 %}

## The Static Assets

Create a folder called “**assets**” in the “src” directory and put the image below inside of it.


![Banner Image](https://paper-attachments.dropboxusercontent.com/s_EA8C6DE4BE9641147D54DD51342EFE156137984675A81D934154815D89C83216_1687692095002_heroimage.jpg)


Now execute `**yarn start**` to have you application running on the browser.

**Congratulations on building a web3 cinema ticket booking Dapp that features real-time chat communication with the CometChat SDK!** If you're looking for a powerful and versatile chat SDK that can be used to add chat functionality to any application, I encourage you to try out CometChat. CometChat offers a wide range of chat features, including 1-on-1 chat, group chat, file sharing, and more. It's also very easy to integrate with other platforms, making it a great choice for developers of all skill levels.

[**Here is a link to the CometChat website where you can learn more about the SDK and how to get started.**](https://try.cometchat.com/oj0s7hrm5v78)

## Conclusion

Dapp Cinemas is a decentralized application that uses blockchain technology to revolutionize the movie industry. The project offers a comprehensive solution for movie management, showtime scheduling, ticket booking, and revenue tracking.

The smart contracts on the Ethereum blockchain ensure seamless and transparent operations. The front-end interface provides an intuitive user experience, and the real-time chat functionality enhances user engagement. Comprehensive testing ensures the reliability and correctness of the smart contracts. 

Dapp Cinemas demonstrates the potential of blockchain technology in revolutionizing the movie industry, providing benefits such as increased transparency, secure transactions, and efficient revenue management.

If you're interested in learning more about web3 development, be sure to subscribe to our [**YouTube channel**](https://www.youtube.com/@dappmentors?sub_confirmation=1) and [**check out website**](https://dappmentors.org/). We have a wide range of tutorials, courses, and books that can help you get started.

Till next time, all the best!


## About Author

I am a web3 developer and the founder of Dapp Mentors, a company that helps businesses and individuals build and launch decentralized applications. I have over 7 years of experience in the software industry, and I am passionate about using blockchain technology to create new and innovative applications. I run a [**YouTube channel called Dapp Mentors**](https://www.youtube.com/@dappmentors?sub_confirmation=1) where I share tutorials and tips on web3 development, and I regularly post articles online about the latest trends in the blockchain space.

**Stay connected with us, join communities on**
Discord: [Join](https://discord.gg/PgFDUVT6n9)
Twitter: [Follow](https://twitter.com/iDaltonic)
LinkedIn: [Connect](https://www.linkedin.com/company/dapp-mentors)
GitHub: [Explore](https://github.com/Daltonic)
Website: [Visit](https://dappmentors.org/)