# Tutorials

## WALKTHROUGH

### 1. Clone Calculator app (or any other React JS app)

```bash
git clone https://github.com/madzadev/calculator.git
```

Open the repository in your choice of code editor and run command <mark style="color:blue;">`npm install`</mark> to install the dependencies. You can test out the original app by running the command <mark style="color:blue;">`npm run start`</mark>.

### 2. Install DPAPI Packages

```bash
npm i @dpapi/server @dpapi/react
```

{% hint style="warning" %}
Remember to first uninstall React v16 and then re-install React v18

<mark style="color:orange;background-color:blue;">`npm uninstall react react-dom`</mark>

<mark style="color:orange;">`npm install react@18.2.0 react-dom@18.2.0`</mark>
{% endhint %}

### 3. Create RoomProvider

Wrap the child elements with <mark style="color:blue;">`RoomProvider`</mark>

<details>

<summary>src/index.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">import React from "react";
import ReactDOM from "react-dom";
<strong>import {RoomProvider} from "@dpapi/react";
</strong>
import App from "./App";
import "./index.css";

const rootElement = document.getElementById("root");
ReactDOM.render(
<strong>  &#x3C;RoomProvider>
</strong>    &#x3C;App />
<strong>  &#x3C;/RoomProvider>,
</strong>  rootElement
);
</code></pre>

</details>

### 4. Add Multiplayer Functionalities

<mark style="color:blue;">`useContext`</mark> is used to create client socket connection.\ <mark style="color:blue;">`joinRoom`</mark>, <mark style="color:blue;">`roomCount`</mark> and <mark style="color:blue;">`liveCursors`</mark> are added to the React App which shall be rendered.

<details>

<summary>src/App.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">// Retain all app import statements 👈🏼
<strong>import {useContext} from "react";
</strong><strong>import "./App.css";
</strong><strong>import {
</strong><strong>  clientSocket,
</strong><strong>  roomCount,
</strong><strong>  liveCursors,
</strong><strong>  joinRoom,
</strong><strong>} from "@dpapi/react";
</strong>
// Retain original calculator app code 👈🏼

const App = () => {
<strong>  const socket = useContext(clientSocket);
</strong><strong>  joinRoom("calcRoom", socket);
</strong><strong>  const usersCount = roomCount("calcRoom", socket);
</strong><strong>  const cursors = liveCursors("calcRoom", socket);
</strong>
  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code 👈🏼
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
<strong>    &#x3C;div className="App"> // ❗ Remember to add a CSS file
</strong><strong>      &#x3C;h1>Number of users in the room: {usersCount}&#x3C;/h1>
</strong><strong>      {cursors.map((cursor, index) => {
</strong><strong>        if (cursor.socketId !== socket.id) {
</strong><strong>          return (
</strong><strong>            &#x3C;div
</strong><strong>              key={cursor.socketId || index}
</strong><strong>              className="other-cursor" // ❗ Style your cursors with CSS
</strong><strong>              style={{
</strong><strong>                left: cursor.x,
</strong><strong>                top: cursor.y,
</strong><strong>              }}
</strong><strong>            />
</strong><strong>          );
</strong><strong>        } else { return null; }
</strong><strong>      })}
</strong><strong>      &#x3C;br />
</strong>      &#x3C;Wrapper>
        // Retain original calculator app code 👈🏼
      &#x3C;/Wrapper>
<strong>    &#x3C;/div>
</strong>  );
};

export default App;
</code></pre>

</details>

### 5. Cursor CSS Elements

Create a new file called <mark style="color:blue;">`App.css`</mark> in the <mark style="color:blue;">`src`</mark> directory.

<details>

<summary>src/App.css</summary>

<pre class="language-css" data-line-numbers><code class="lang-css"><strong>.App {
</strong><strong>  text-align: center;
</strong><strong> }
</strong><strong>
</strong><strong>.other-cursor {
</strong><strong>  position: absolute;
</strong><strong>  width: 10px;
</strong><strong>  height: 10px;
</strong><strong>  border: 0;
</strong><strong>  border-radius: 50%;
</strong><strong>  background-color: red;
</strong><strong> }
</strong></code></pre>

</details>

## <mark style="color:purple;">EXTRA: Custom Cursor</mark>

In this section, we will assign random cursor icons to every client.\
This is useful for providing a fun and dynamic user experience in a shared space.

We make use of React <mark style="color:purple;">`useState`</mark> & <mark style="color:purple;">`useEffect`</mark> hooks to assign and re-render cursor icons.

<details>

<summary>src/App.js</summary>

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">// Retain all app import statements 👈🏼
<strong>import {useEffect} from "react";
</strong>// Retain original calculator app code 👈🏼

<strong>const cursorUrlArray = [
</strong><strong>  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Guyman-Off-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/everaldo/starwars/128/Darth-Vader-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/everaldo/starwars/128/clone-old-icon.png",
</strong><strong>  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Thomas-On-icon.png",
</strong><strong>];
</strong>
const App = () => {

  // Retain DPAPI functions 👈🏼
  
<strong>  const [cursorUrl, setCursorUrl] = useState("");
</strong><strong>  useEffect(() => {
</strong><strong>  setCursorUrl(
</strong><strong>    cursorUrlArray[Math.floor(Math.random() * cursorUrlArray.length)]
</strong><strong>  );
</strong><strong>  },[]);
</strong>
  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code 👈🏼
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
        // Retain DPAPI code from above 👈🏼
              &#x3C;div
              key={cursor.socketId || index}
              className="other-cursor" // ❗ Style your cursors with CSS
              style={{
                left: cursor.x,
                top: cursor.y,
<strong>                backgroundImage: `url(${cursorUrl})`,
</strong>              }}
        // Retain all other code from above 👈🏼
    );
};

export default App;
</code></pre>

</details>

{% hint style="info" %}
Inside the <mark style="color:blue;">`useEffect`</mark> hook, the <mark style="color:blue;">`setCursorUrl`</mark> function is called to randomly select one of the <mark style="color:blue;">`cursorUrl`</mark> values from the array and set it as the initial state of <mark style="color:blue;">`cursorUrl`</mark>
{% endhint %}

### <mark style="color:purple;">Update Cursor CSS Elements</mark>

<details>

<summary>src/App.css</summary>

<pre class="language-css" data-line-numbers><code class="lang-css">.App {
  text-align: center;
 }
 
.other-cursor {
    position : absolute;
    width: 35px;
    height: 35px;
<strong>    background-size: contain;
</strong><strong>    border-radius: 100%;
</strong>}
</code></pre>

</details>
