Build a coupon code manager app in 30 minutes
Tags: javascript, beginners, tutorial, codenewbie
Published: 2022-03-29 10:57:24

> In this article, we will see a start to finish guide for building a coupon code manager app that will let you create coupon codes and manage their discounts, descriptions, and expiry dates.

This tutorial will guide you to build a CRUD app that will let you create new coupons, edit or delete existing coupons. We will be using [ToolJet](https://tooljet.com/) to build this application and will use Google Sheets as the data source.

## Prerequisites

- ToolJet (https://github.com/ToolJet/ToolJet ): A free and open-source low-code platform that allows you to quickly build applications. Sign up [here](https://tooljet.com/).

- Google Sheet: A sheet with some existing data is preferred. You can duplicate the one that I used [here](https://docs.google.com/spreadsheets/d/1-TWBdgwbl-HrNooECdLXjvhWNly1qDgJYgt-dtpIpJg/edit?usp=sharing).

Here's a glimpse of the app that you'll be building:

![app](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-25-at-4.10.26-AM.png)

I have broken down the whole tutorial into the following parts:

- **Build the user interface**
- **Create the queries**
- **Edit widget properties and connect queries**

Let's jump into the ToolJet and click on **Create new application** button on the top-right corner of the dashboard. Once entered the app editor, you'll be asked to create a version - enter a version name and click **Create**.

Before we start creating an app - let me give you a quick walkthrough of the ToolJet app editor:

![app-editor](https://blog.tooljet.com/content/images/size/w1600/2022/03/Screenshot-2022-03-25-at-4.02.40-PM.png)

---

## Build the user interface

Let's start with building the user interface of our application. To build the user interface, we will be using widgets like containers, image, text, text-input, button, modal, and table.

Let's start building the header first:

- Drag a container to the canvas and adjust its height and width accordingly, and place it on the top.
- Now click on the container's **widget handle** to open **inspect panel** on the right sidebar. We can edit the properties and add styling to any component/widget from inspect panel. Go to the **Styles** and add a background color to the container. You can either choose a color from the picker or add a hex-code.
- Now let's drag an **image** widget inside the container. We will use this image widget to display the logo of our app. Just click on the widget to open inspect panel and in the **URL** field enter the URL for and png or SVG logo.
- Finally, drop a **text** widget inside the container to give a title to our app. Open inspect panel, in the text field enter the title for your app. You can also use HTML tags to style text.

Now we are done with the header of the app:

![header](https://blog.tooljet.com/content/images/size/w1600/2022/03/Screenshot-2022-03-25-at-2.51.32-PM.png)

Let's build the main section of our app. In this section, we will be working mainly with button, modals, and a table. The button will be used to popup a modal that will have a form to create a new coupon. The table will be used to display, edit, and delete the coupons. The table will also have two action buttons that will be used for editing and deleting the coupons. Now, let's build the body:

- Drag a **container** on the canvas below the header, adjust its height and width accordingly. Add a light background to the container from the Styles in the inspect panel.
- Add a **text** widget in the top-left of the container and in the text field enter All Coupons. You can style it by using the HTML tags and changing the text color in styles tab.

![text](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-28-at-3.04.19-PM.png)

### UI for showing the coupons in table

- Drag and drop a table and edit its properties.
  - Set the value for the **Table data** field as to `{{queries.read.data}}` where the **read** is the name of the query that we will create later in this tutorial, **data** is the data that the query will hold.
  - In the Columns section, add all the required columns that you want to display in the table. Make sure to provide the same key name as the column name in the google sheet.
  - Add two action buttons - **Edit coupon** & **Delete Coupon**.
  - You can style the table widget by changing its border radius to `10` and the action button border radius to `5`. We will modify our table later once we are done creating the queries.

![tableui](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-28-at-3.05.31-PM.png)

### UI for creating a coupon form

- Add a **button** on the top-right corner of the container. Click on the button handle to open inspect panel and edit the properties: **Button text**: `Create Coupon`, **Background color**: `#705EC5` (hex), and **Border radius**: `10`.

![createUI](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-28-at-3.04.36-PM.png)

- Drag a **Modal** below the table and click on it to edit its properties. We'll add the Title as Create Coupon.
- Open `Create Coupon` button properties and create a **handler** on `On-click` **event** and perform `show modal` **action**

![createUI1](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-28-at-6.30.35-PM.png)

- Now, when you'll click on the button it will open up the modal that you added. You can now drag and drop more widgets on this modal to create a form. We'll use the following widgets to create a form for creating a coupon:
  - **Text** widgets for adding titles next to the fields. ex: Coupon code, description, discount, free delivery etc.
  - **Text input** widget for coupon code field. You can also use validation to accept only certain type of words for coupon code.
  - **Text area** for description.
  - **Number input** widgets for discount and redemption limit values. You can set minimum value as `10` and maximum value as `100` for discount and `1` to `10` for redemption limit respectively.
  - **Radio button** widget for free delivery value. Set default value as `{{'no'}}`, option values and option labels as `{{["Yes", "No"]}}`.
  - Date picker for redeem before value. In default value field use momentjs to get current date `{{moment().format("DD/MM/YYYY")}}`. You can also add a validation to only accept dates in future: `{{moment(components.datepicker3.value, 'DD/MM/YYYY').isSameOrAfter(moment().startOf('day')) ? true : 'Selected date is in the past'}}`
  - **Create coupon** button for creating a coupon that will run the `create` query and close the modal. We will add two event handlers in this button: first to trigger create query and second to close the modal.

![createUI2](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-25-at-4.08.30-AM.png)

### UI for editing the coupon form

We will use the same form UI that we used in the form for creating coupon. We will select the modal that we added earlier and press **ctrl/cmnd+d** for duplicating the modal and will create a modal 2 with the same widgets as they were inside the modal1.
We will add an event handler to the **edit coupon** button in table to show this modal(modal2).

In **modal2**, for all the fields we will set the default value as `{{components.table1.selectedRow.key}}` (key is the column name in google sheet). This will auto-fill the form values from the selected row in table.
You need to change the text in button from **Create coupon to Update Coupon** and replace the query in handler from create to update.

![editui](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-25-at-4.08.54-AM.png)

---

## Create the queries

For this application, we will need to build 4 queries and these queries will perform read, create, update and delete operations on Google Sheet respectively.

> 💡 Check out the [docs](https://docs.tooljet.com/docs/data-sources/google.sheets) for all the operations available in Google Sheet datasource.

### Connecting data source

Before we create queries, we need to connect the data source in our application. We will be using Google Sheet as the data source. To connect the data source, go to the data source manager on the left sidebar and click on the `+` button to add a data source. Select Google Sheet from the list of data sources in the popup.
In the next popup, you'll be asked to choose either **Read-only** or **Read or write** permission that you will grant ToolJet. Select Read or write permission and then click on **Connect to Google Sheet**, Authorize ToolJet and then click on **Save data source** button.

![datasource](https://blog.tooljet.com/content/images/size/w1600/2022/03/Screenshot-2022-03-29-at-1.49.24-AM.png)

Let's start building the queries:

## Reading coupons

Now that we have successfully connected our data source, let’s run a read operation to read from google sheet and show it in our table.

- In the query panel, click on the `+` button to create a new query and then Select `Google Sheet` from the available data sources.
- Select `Read data from the spreadsheet` option from the **Operation** dropdown.
- Enter the **spreadsheet id**. You'll find the spreadsheet id in the URL of your google sheet. ex: **https://docs.google.com/spreadsheets/d/1tVwSon7Xp9HYOavlmx9oW_jKlZL2qrqGVImOmShtsVI/edit#gid=0**
The bold string is the spreadsheet id.
- Rename this query `read` from the field on the top-right of the query panel.
- Go to the **Advanced** tab and toggle on `Run query on page load?`. Turning this on will run this query every time the app is opened.
- Click on **Create** button to save this query.
- Hit the **run** button next to the query on the left sidebar of the query panel. This will fetch all the existing data in the google sheets. You can check the data returned by the query in the inspect panel.

> 💡 You can also hit the **Preview** button if want to take a look at the data without executing the query. 

![readingQuery](https://blog.tooljet.com/content/images/size/w1600/2022/03/Screenshot-2022-03-28-at-5.48.09-PM.png)

## Deleting a coupon code

Create a new Google sheet query the same way we created the `read` query. We'll name it as `delete`.

- Choose the `delete a row from spreadsheet` option from the **Operation** dropdown.
- Enter the **GID**, mentioned in the URL of the spreadsheet.
- In the `delete row number` field, we will enter: `{{parseInt(components.table1.selectedRowId)+2}}`. We are using the table's **selectedRow** property to get the number of that row from the table and using **parseInt** function to convert the incoming string to a number as the field only accepts a numerical value. We are adding 2 to the number since the number returned by the selectedRow property is with respect to the table in ToolJet but in google sheet, it will be `+2` to the current row number.
- Click on **Create** to save the query.

## Create a coupon

Create a new google sheet query and select `Append data to a spreadsheet`. Enter the **spreadsheet id** and leave the **Sheet** field blank (if left blank it chooses the first sheet by default).

In the **Rows** field,  enter:
`{{[{id: 'id_' + (new Date()).getTime(), name: components.textinput4.value, description: components.textarea2.value, discount: components.numberinput4.value, free_delivery: components.radiobutton2.value, redemption_limit: components.numberinput5.value, redeem_before: components.datepicker3.value, created_at: moment().format("DD/MM/YYYY") }]}}`
Where the value for **id** key is generated randomly using javascript **date getTime()** method and for **created_at** we're using momentjs to get the current date (i.e date of the creation of coupon). For all other keys we will get the values from the widgets placed in **modal1**.

![createCoupon](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-25-at-4.13.06-AM.png)

## Updating a coupon

Create a new query, select Google Sheets as the datasource and enter the following values:

- **Operation**: `Update data to a spreadsheet` for updating the data
- **Spreadsheet ID**: ID from the URL of Google Spreadsheet
- **Where**, **Operator**, and **Value**: For Where we will use the `name` which is the key of a column, for Operator we will use `===` (used to check equality), and for Value, we will use `{{components.table1.selectedRow.name}}` i.e the value of name from the selected row in table.
- **Body**: `{{({name: components.textinput5.value, description: components.textarea3.value, discount: components.numberinput8.value, free_delivery: components.radiobutton3.value, redemption_limit: components.numberinput7.value, redeem_before: components.datepicker4.value})}}`

![updateCoupon](https://blog.tooljet.com/content/images/2022/03/Screenshot-2022-03-25-at-4.16.04-AM.png)

Now, we have successfully created the four queries to perform the read, create, update and delete operations.

>💡 You can add the event handler from the Advanced tab to perform an action whenever the query is successful. For example, you can create an event handler in each of the Append, Update and Delete queries to run the Read query - this will reload the table with the new data every time the user adds, deletes, or updates data.
You can also show a custom success message whenever a query is successful from the advanced tab. 

---

## Edit widget properties and connect queries

### Display coupons on table

Click on table to open its properties and in table data field enter: `{{queries.read.data}}` this will get the data from read query. Now add columns to display on the table:

- Column name: **Name**, key: **name**
- Column name: **description**, key: **description**
- Column name: **discount**, key: **discount**, Text color: `{{ cellValue >= 30 ? 'green' : 'red'}}` if the discount is greater than or equals to 30 then the text color will be green else red.
- Column name: **free_delivery**, key: **free_delivery**, Text color: `{{ cellValue === 'yes' ? 'green' : 'red'}}` if the delivery is free i.e yes then the text color will be green else red.
- Column name: **redemption_limit**, key: **redemption_limit**
- Column name: **redeem_before**, key: **redeem_before**
- Column name: **created_at**, key: **created_at**

Edit the properties of two action buttons that we created before:

- **Edit coupon**: Add a handler to this action button for **On-click** event to perform **show-modal** action and select **modal2**.
- **Delete coupon**: Add a handler to this action button for **On-click** event to **run a query** action and select **delete** query.

In **Options**, toggle on the **highlight selected row** to show the selected row in the table. In loading state field, click on **Fx** and enter `{{queries.create.isLoading || queries.update.isLoading ? true : false}}` to show a loading state on the table whenever an update or create runs.

>💡 You can always make style changes to any widget from the styles tab.

## Create coupon

Click on the Create coupon to open the **modal1**. Add the event handler to the button run the `create` query.

Now, we have connected all our queries and your coupon code manager is good to go. Make the application live by clicking on the **Release** button on the top-right corner of the app editor.

---

Congratulations! 🥳 You’ve successfully created Coupon code manager app. If you have any questions feel free to join our [Slack community](https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg) or send us an email at hello@tooljet.com