Accelerate your learning by starting with the full source code of my first project
Tags: react, chakraui
Published: 2021-03-24 06:25:34

This is my very first project and I'm giving the code away to help other beginners to accelerate their learning.

![mvp](https://dev-to-uploads.s3.amazonaws.com/i/u2t7kzo1m8i6znsccqu4.jpeg)

This article will guide you through setting up and deploying a production-ready app and utilizes a [Create-React-App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app) (CRA) boilerplate to get us at a good starting point and [Strapi](https://strapi.io/) for building our api end-points and auth and a Postgres DB for storing data.


The idea behind it is that it's a drinks ordering app. Users can order drinks off a menu on their phone. It's intended to be used in-house and then the orders apear on a bar management interface. Super simple app, but the concepts of this app can be used to create virtually anything, after all every app boils down to a C.R.U.D (*Create. Read. Update. Delete*) app.

There are three repo's that complete this app, two CRA repos and one a strapi repo. All repos are hosted as their own app on Digital Ocean's App platform, in a Microservice architecture-like setup. 

The ordering (drinks-user) and the management (drinks-bar) sides of the app, build off of Create-React-App, with the drinks-app using [Chakra-ui](https://chakra-ui.com/) for a small bit of functionality/ animation.

I will provide the CRA repos and I encourage you to check out [Thew Dhanat's](https://twitter.com/ThewDhanat) article to set up and host your own Strapi app.

Don't forget to install Postgresql on the project with `npm install pg` before deploying on Digital Ocean and you need to create a production db separately to add it as an existing one, instead of the dev db in Thew's article if you want to do a full production build.   

My repo's will be linked at the bottom of the article.

{% post thewdhanat/strapi-quickstart-on-digitalocean-app-platform-502j %}


Strapi is fairly straight-forward, you generate the code visually and it's easy to get set-up with [their quick-start docs](https://strapi.io/documentation/developer-docs/latest/getting-started/quick-start.html#_1-install-strapi-and-create-a-new-project).

If you need Strapi help, I strongly recommend [Alex the Entreprenerd on YouTube](https://www.youtube.com/channel/UCMguCMq25nEqlHlr17iINNw) and he has a great course on Udemy too and/or you can join Strapi's Forum or slack channel you can find through [their site](https://strapi.io/).

The app for people to submit orders (drinks-user) is just a form and to manage state, I'm using [React-easy-state](https://github.com/RisingStack/react-easy-state#readme) 

``src/state/OrderStore``
```javascript
import { store } from "@risingstack/react-easy-state";

const OrderStore = store({
  items: [],
  TableNum: "",
});

export default OrderStore;
```


I'm then importing the state whenever I need to use it, as you can see at the top of ``src/components/UIForm`` 
and then the initial render, I'm getting the data from the Strapi endpoint e.g ``${baseUrl}/item``, with useEffect and then pushing each Item from my the request into the empty item array of the state, by pushing in a for loop on the initial fetch.
```javascript
import React, { useEffect } from "react";
import Item from "./Item";
import axios from "axios";
import OrderStore from "../state/OrderStore";
import { view } from "@risingstack/react-easy-state";
const UIForm = view(({ items }) => {
  let baseUrl = process.env.REACT_APP_BASEURL;
  const getMenu = async () => {
    const menuItems = await axios.get(`${baseUrl}/items`);
    for (let i = 0; i < menuItems.data.length; i++) {
      OrderStore.items.push({
        itemName: menuItems.data[i].name,
        id: menuItems.data[i].id,
        checked: false,
      });
    }
  };

  useEffect(() => {
    getMenu();
  }, []);

... 
```

Here I'm rendering a UIForm component with as many item components from ``src/components/item`` for many items that we get back from the endpoint.

```javascript
let setInput = (e) => {
    OrderStore.TableNum = e.target.value;
  };

  let setOrder = async (e) => {
    e.preventDefault();

    for (let i = 0; i < OrderStore.items.length; i++) {
      if (OrderStore.items[i].checked === true) {
        const res = await fetch(`${baseUrl}/orders`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            drink: OrderStore.items[i].itemName,
            tableNum: OrderStore.TableNum,
          }),
        });
        const data = await res.json();
        console.log(data);
      } //If statement ends
      OrderStore.items[i].checked = false;
      console.log(
        `${OrderStore.items[i].itemName} is ${OrderStore.items[i].checked} `
      );
    } // For statement ends
    OrderStore.TableNum = "";
  };

  return (
    <div className="item-container">
      <form onSubmit={setOrder}>
        {OrderStore.items.map((item) => (
          <Item
            key={item.id}
            name={item.itemName}
            checked={item.checked}
            value={item.itemName}
            id={item.id}
          />
        ))}

        <div className="submit-div">
          <label htmlFor="tableNum" className="table-label">
            Table Number
          </label>
          <input
            type="text"
            name="tableNum"
            value={OrderStore.TableNum}
            onChange={setInput}
          ></input>
          <button>Order</button>
        </div>
      </form>
    </div>
  );
});
export default UIForm;
```

I'm using the [Axios](https://github.com/axios/axios) package to fetch data, which the official Strapi docs recommend and I prefer it to the browser fetch Api tbh. The `view()` wrapping the component is from the state library and assures it re-renders when the state is updated.


![user-repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25pe5nasbnu6i72xdsk6.png)
 
Above you'll see my folder structure for this repo and I recommend creating a .env file in the root directory, like I have, to save an environment variable to ensure changing the URL of the hosted app is a breeze and you only need to change it in one place, I've also set it up to work that way if you're cloning my project. 

Environment variables are the way you can save api and secret keys for your projects in the same repo without uploading sensitive information to your git repos, by telling your .gitignore file, in the root directory, to ignore the file extension when uploading to git. 


![gitignorefile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xplcv7v00k9uy2df3xcn.png)

You'll need to prefix environment variables for React apps, with REACT_APP_ for it to work.

My CRA's .env's both have the following environment variables
```
//Strapi URL
REACT_APP_BASEURL=http://localhost:1337 
``` 
1337 is the port that Strapi runs on in development mode and you'll notice that's the port Thew gets us to set the port of our Digital ocean app to. It's not really needed in development mode, but we've set it up for deployment, by using setting it to be storing it in a variable in our code
```javascript
let baseUrl = process.env.REACT_APP_BASEURL;
```

Now when we deploy the repo, we can set the environment variable through Digital Ocean and it will look something like this
`REACT_APP_BASEURL`= `https://drinks-backend-{you-unique-id}.ondigitalocean.app`
 
You'll need to make sure you change the keys in the setOrder function of the body, where you make the post request, to be the same as the headers of the Strapi collection... see below 

```javascript
 body: JSON.stringify({
            drink: OrderStore.items[i].itemName,
            tableNum: OrderStore.TableNum,
          })
```

![feilds](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mp0rzw35vait62h7ulr7.png)

You'll need to do a similar thing in pages that make requests in the drinks-bar app.

Currently, the way it is, anyone can make an order and auth is only on the management app. The login page makes the auth request and stores it in state of the useContext and therefore the whole app will be able to use the user credentials.

I deployed these as separate apps on Digital Oceans App platform and to do so yourself, you can go through a similar process to Thew. Select the Repo >> Select Static site (for the CRA's)

![static](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqa3vmg44o462bkm5thh.png)
 

Repeat for the other repo and done!

##My Repo's
[drinks-user](https://github.com/MVAodhan/drinks-user) (the order form)
[drinks-bar](https://github.com/MVAodhan/drinks-bar) (the bar management app)

Follow me on [Twitter](https://twitter.com/suiteasdesign) to give me feedback and let me know what you end up building.

Thanks for visiting my first ever piece of content!