Getting Started Full Stack Tutorial Part 3: Build the coffee store web app

Part 3: Build the coffee store web app

time to complete
20 minutes

Introduction

In part 3 of the tutorial, you will see the online storefront for your coffee operation. It uses the Vue.js JavaScript framework to create a single-page web app (SPA). Teaching Vue.js is beyond the scope of this tutorial, but you get a flavor for how it was built, and see how the REST services you created in Part 2 are used by this app.

diagram of part 3 web app


tip
Need InterSystems IRIS?
Get a free, online development sandbox here. Log in with your InterSystems universal account, or register for one below.

Customize the code

The code has all been written for you, so let’s run it and see how it works. First, let’s start installing some required packages. That will take a few minutes, and we can make some edits those download. In the Sandbox IDE’s terminal, enter the following commands.

  cd /home/project/quickstarts-full-stack/frontend
  npm install
  npm install yarn

Now, let’s put your personal IRIS server’s address into the source code.

  1. Open /home/project/quickstarts-full-stack/frontend/src/views/Home.vue
  2. Find and replace localhost:52773 with -- cannot display value - please provision a sandbox
  3. Repeat the find and replace in /home/project/quickstarts-full-stack/frontend/src/views/Sale.vue
  4. Repeat the find and replace in /home/project/quickstarts-full-stack/frontend/src/components/ProductCard.vue

Now let’s run the app in a built-in development web server.

  1. Back in the Sandbox IDE’s terminal, enter the following commands.
      cd /home/project/quickstarts-full-stack/frontend
      yarn serve
    
  2. In your browser, enter this URL:
    http://-- cannot display value - please provision a sandbox:-- cannot display value - please provision a sandbox

View the storefront

You should see a list of products for sale that looks something like this.

storefront home page

Product listing

Let’s talk about how that happens with Vue.js. Like most frameworks such as React and Angular, URLs are “routed” to a component. Look at /home/project/quickstarts-full-stack/frontend/src/router/index.js to see that the default URL path, “/”, gets routed to the Home component, which can be found in the file /home/project/quickstarts-full-stack/frontend/src/views/Home.vue. That view calls the GETPRODUCTS REST service, which returns JSON listing all the products for sale that have been roasted in the last 5 days (passing a parameter of 1, or no number at all, asks for only freshly roasted bags). The GETPRODUCTS request looks like this:

GET https://-- cannot display value - please provision a sandbox/api/coffeeco/catalog/getproducts/1

And the response looks like this:

{
    "rowcount": 5,
    "products": [{
        "catalog_id": "1",
        "product_code": "BRAZILDARK",
        "quantity": 38,
        "time_roasted": "2021-02-09 09:00:00",
        "roasting_notes": "Full bodied and low acidity. Thick, creamy, nutty and semi-sweet.",
        "img": "brazil_dark.jpg",
        "price": 13.99
    }, {
        "catalog_id": "2",
        "product_code": "ETHIOPIAMEDIUM",
        "quantity": 40,
        "time_roasted": "2021-02-08 09:00:00",
        "roasting_notes": "Sweet floral notes, followed by the potent citrus notes, perfectly married into bergamot.",
        "img": "ethiopia_medium.jpg",
        "price": 14.99
    }, {
        "catalog_id": "3",
        "product_code": "GUATEMALALIGHT",
        "quantity": 120,
        "time_roasted": "2021-02-09 17:30:00",
        "roasting_notes": "Full body and a rich chocolatey-cocoa flavor, and a toffee-like sweetness.",
        "img": "guatemala_light.jpg",
        "price": 11.99
    }, {
        "catalog_id": "4",
        "product_code": "SUMATRADARK",
        "quantity": 80,
        "time_roasted": "2021-02-07 13:01:30",
        "roasting_notes": "Smooth and chocolaty with a sweet edge and minimal earthiness.",
        "img": "sumatra_dark.jpg",
        "price": 12.99
    }, {
        "catalog_id": "5",
        "product_code": "SUMATRALIGHT",
        "quantity": 40,
        "time_roasted": "2021-02-07 09:00:00",
        "roasting_notes": "This rich and juicy Sumatra carries sustained notes of cherry and citrus.",
        "img": "sumatra_light.jpg",
        "price": 12.99
    }]
}

To see how the database call behind the REST service is performed, look at the SellProduct ClassMethod in /home/project/quickstarts-full-stack/services/cls/ICO/Handler.cls.

Home.vue then iterates through that JSON object, creating a ProductCard (see /home/project/quickstarts-full-stack/frontend/src/components/ProductCard.vue) for each item in the JSON. ProductCard.vue just knows how to display a single product and create the UI for ordering it.

Now, click on the “Last chance” tab. You should see a shorter list of products (if you don’t, then you need to modify a couple time_roasted values in the ICO.catalog table to be older than 5 days).

screenshot of the last chance page

Older products on the last chance page

This invokes the Sale “view” (see /home/project/quickstarts-full-stack/frontend/src/views/Sale.vue), which makes a call to the same backend service, but with a parameter telling the service to return coffee older than 5 days (by passing any number other than 1). The REST call looks like this:

GET /api/coffeeco/catalog/getproducts/2

And the response looks like this:

{
    "rowcount": 1,
    "products": [{
        "catalog_id": "10",
        "product_code": "SUMATRALIGHT",
        "quantity": 40,
        "time_roasted": "2021-02-02 09:00:00",
        "roasting_notes": "This rich and juicy Sumatra carries sustained notes of cherry and citrus.",
        "img": "sumatra_light.jpg",
        "price": 12.99
    }]
}

 

Just like Home.vue, Sale.vue also uses the ProductCard component to display products, but in the fetchProducts function it discounts the price by 3 dollars before passing the data on to a ProductCard. This is a simple example of reusing components to simplify your code, and also shows the separation between pricing and inventory management.

Making a purchase

Finally, let’s buy some coffee!

Toggle the quantity on a product and click “Place Order”. You should get a pop-up alert showing you the order has been completed. (Of course this is an unrealistic sample. In a real app you’d build a shopping cart and not place the order until the customer has made a payment. ) but this simple example shows how the ProductCard calls out to the SellProduct REST service to take the ordered coffee beans out of the catalog.

The REST call takes this form:
POST /api/coffeeco/catalog/sellproduct/{product's catalog id}/{quantity of bags sold}

Since this is a POST request, it can’t be made from the browser. So open a new Terminal window in the IDE (Terminal menu -> New Terminal), and run this command:

curl -X POST https://-- cannot display value - please provision a sandbox/api/coffeeco/catalog/sellproduct/1/2

And the response looks like this:

{
    "catalog_id": 1,
    "product_code": "BRAZILDARK",
    "quantity": 36,
    "price": 13.99,
    "time_roasted": "2021-02-09T09:00:00Z",
    "roasting_notes": "Full bodied and low acidity. Thick, creamy, nutty and semi-sweet.",
    "img": "brazil_dark.jpg"
}

Here are some ways to play with the app a little more:

  1. Keep on ordering bags of coffee until the inventory is too low to satisfy your order. Eventually you should be able to make the product disappear from the storefront.
  2. If you have some web development experience, modify the CSS of the ProductCard.vue component (it’s found at the end of the file in the <style> section).
  3. If you have Vue.js experience, try changing the basic JavaScript alert message used in the processOrder function of ProductCard.vue to say something more interesting. Or even design your own component to show this information instead of a pop-up alert!

Next Steps

Hopefully you’ve enjoyed this tour of the basic functionality of InterSystems IRIS. Let’s summarize what we learned.

  • In Part 1, you used SQL to create tables and load data, typing raw SQL and using it programmatically in Python.
  • Part 2 introduced ObjectScript, our fast and flexible database programming language, and showed you how to build REST services with it.
  • Here in Part 3, you learned how to build the customer-facing front-end web app in a popular JavaScript framework.
We'd love to speak with you about your next project! Use the chatbot to get in touch by clicking here.