Movie Ticket Booking App using SAP AppGyver

Purpose

This blog is my entry for the SAP Low Code No Code Challenge.The purpose of this blog is to share my learning and the experience I got while learning SAP AppGyver. I wanted to learn front end UX/UI after working as an ABAP Developer for a long time and this challenge was a good fit for me to start with my front end journey.

If we are learning any new programming language, the first application we will be creating is either a weather app or a to-do list. So I wanted to do something new and came up with this movie ticket booking app.

My  App

Built-in Navigation is disabled as I wanted a customized navigation tab consisting of a back button, brand name, and booking history icon. All the pages are stretched to the view port to occupy the entire screen width and height.

Glimpse of my app

My application consists of a total of six pages.

Pages%20of%20my%20application

Pages of my application

Home Page

It has a list of movies running in cinemas. For movie details and posters, I am using OMDbAPI’s RESTful web service.

If we call the RESTful API using the above service, the output will be in JSON format, which consists of the movie list, total number of movies found and the response to our call.

API%20output

API output

Below are the configurations done in AppGyver as part of the REST API direct integration to get only the required information for our application.

REST%20API%20direct%20integration%20resource%20Base%20details

REST API direct integration resource Base details

We need to configure GET COLLECTION as the output will be multiple records based on the filter conditions passed during the API call.

Get%20Collections%20setting

Get Collections

As you know from the API output image it is clear that we are getting the list of movie details in object format under JSON key Search. So, Search is maintained in the Response Key path to retrieve only the necessary details into our application.

Schema%20of%20the%20details%20retrieved%20from%20API

Schema of the details retrieved from the API

On the Home Page, after the navigation container, the list item container is repeated inside the scroll view based on the list retrieved from the REST API call using Get record Collection flow logic when the page is mounted.

I wanted a welcome screen to be displayed for a couple of seconds when the application opens for the first time. This was achieved by creating a new container with position as absolute and Z-index as 1, and the visibility property is set to application variable flag, which gets set after some time when the page is mounted for the first time.

Now that the home page is completed, I need to navigate to the show time page when the book tickets container is clicked on the movie item container.

Navigating%20to%20next%20page%20with%20selected%20movie%20details%20as%20page%20parameters

Navigating to next page with selected movie details as page parameters

Show Time

The Show Time page consists of five parts i.e. Movie poster, Movie title, Show timings, Movie Date and Seats navigation button. Movie posters and movie titles are displayed using Image and Title base components from page parameters.

For show timing, I wanted to hardcode fixed times for all the movies. So I created one app variable named ShowTime as a list of objects with times and provided initial values for it.

As we need varying dates, I have added one custom JavaScript logic to get one week of dates from the current date and set it to a page variable for display when the page is mounted or focused and the page variable is empty.

const DateList = [];
const noOfDays = [0,1,2,3,4,5,6];
noOfDays.forEach( i => {
let ipaDate = new Date();
let b = new Date(ipaDate.setDate(ipaDate.getDate() + i)); let DateNumber = b.getDate();
let DateChar = DateNumber.toString();
if (DateNumber<10){ DateChar = '0' + DateChar;
} let MonthNumber = b.getMonth() + 1;
let MonthChar = MonthNumber.toString();
if (MonthNumber<10){ MonthChar = '0' + MonthChar;
} let YearNumber = b.getFullYear();
let YearChar = YearNumber.toString();
let x = b.toLocaleString("en-US",{ day: 'numeric' });
let y = b.toLocaleString("en-US",{ weekday: 'short' });
let z = b.toLocaleString("en-US",{ month: 'short' }); DateList.push({ Day: y,Date:x, Month:z, FullDate: ( DateChar+'-'+ MonthChar+'-'+ YearChar ) });
}) return { result: DateList }; 

Using repeat properties on ShowTime and DateIteration the time and date of the movie are displayed on the screen with a select seats button.

Three page parameters named FullDate, ShowDateSelected and ShowTimeSelected are created to note down the user selection.

When the show date or show time is selected by the user, the respective page parameters are set and the container is highlighted to indicate user selection using a formula.

User%20Show%20Time%20selection%20logic

User Show Time selection logic

User%20Show%20Date%20selection%20logic

User Show Date selection logic

Formula%20to%20highlight%20User%20selection

Formula to highlight User selection

When you click the Select Seats button, the seat selection page should be triggered by passing page parameters.

Seat Selection

Seat availability for the movie will be based on the movie, date and show time. So I have created an On-Device Storage named ReservedSeats with the seat availability key fields and a list of seats booked.

Sample%20record%20of%20ReservedSeats%20collections

Sample record of ReservedSeats collections

On page mount, a list of seats reserved is retrieved by passing key fields such as imdbId, date, and time to get record collection on ReservedSeats (these three fields are passed as page parameters from the previous page).

The seat selection page is divided into movie details, seats available for selection, total price and confirm seats button.

A seat basically has three states i.e. Booked, Available and Selected. So I have created a page variable named Seats as a list of objects with the mentioned states as type Boolean.

I am considering a theatre capacity of 50 for this application. The Seats variable will have 50 objects with the IsAvailable flag as true when the booking for a show is not done. Suppose all the seats are booked, then the Seat variable will have 50 objects with the IsBooked flag as true. Based on the seat state the color of it is changed for better indication to the user using the formula option.

Custom JavaScript logic is written to generate a list of objects with the respective IsAvailable flag and IsBooked flag based on the get collections record on resource ReservedSeats output.

let arrayTemplete = [...Array(50).keys()];
let reservedData = inputs.input1;
let reservedSeats = [];
let seats = [];
let recordId = "";
if (reservedData != []){ reservedSeats = reservedData[0].ReservedSeats; recordId = reservedData[0].id;
}
arrayTemplete.forEach( a =>{ let c = (a + 1).toString(); if (reservedSeats.indexOf(c) < 0) { seats.push( { id:a , IsAvailable:true , IsBooked: false, IsSelected: false } ) } else { seats.push( { id:a , IsAvailable:false , IsBooked: true, IsSelected: false } ) }
})
return { result: seats, oldId: recordId , reservedData: reservedSeats };

When the available seat is selected by the user the object value is changed using custom JavaScript code.Seat%20object%20value%20change%20based%20on%20state

Seat object value change based on state

The total amount should be calculated based on the number of seats selected multiplied by the cost of a single ticket. So a page variable named NoOfSeatsSelected is created and updated based on user selection after the custom JavaScript logic flow.

When the confirm seats button is clicked, the seat numbers selected by the user and the previous seat number reserved are combined into a single list and the resource ReservedSeats is updated.

To store information about seats booked, I created another on-device storage resource called BookedHistory, which includes an id, movie title, date, time, poster URL, booked seat list, and ticket number. Once the resource is successfully updated, the required details are updated on BookedHistory. Then the Ticket page is triggered with the required page parameters.

Ticket

The ticket page consists of a ticket which has QR details of the booked movie show and the same details in text.

For QR code generation with movie details, I used the goqr API call. We just need to combine all the details and encode them into a URI. Custom JavaScript code to encode the details is below.

var QrData = "Movie:"+ inputs.title+",date:" +inputs.date+ ",time:" + inputs.time +",Seat:" + inputs.seats;
var QrUrl = "https://api.qrserver.com/v1/create-qr-code/?data=" + encodeURI(QrData) + "&amp;size=100x100";//&color=FFFFFF&bgcolor=161621";
return { result: QrUrl };

When the back button is pressed on this page, it should go back to the homepage and not to the seat selection page. So Navigate to root from the marketplace is used to achieve this.

Booking History

The booking History page consists of details retrieved from the BookedHistory resource using a list item container. When the booked ticket is clicked then the ticket page will be triggered by passing the details from that respective list item.

Backend Data

This is just an empty page used to reset the database entries that got saved during development and testing. This page is not linked to any other page in the application.

My Experience

I can say for sure this is a very good start for me to learn front-end development. It was very easy to drag and drop the required components on the left hand side of the screen to achieve the design I had in mind. The good thing was that mapping logics like a flow chart made my job easy.

  • Styles and Layout: Styling the components has a lot of binding options which satisfy the different needs. Previews of layout options are visible as soon as we complete binding.
  • Formula: Predefined formulas are amazing as they are categorized based on the type, documentation on the right hand side and sample output based on the example values provided for the variable will give an idea of whether the formula is suitable or not.
  • Custom JavaScript: Custom codes can be written on top of the flow if we need some logic that is a little bit complex or not possible using simple or predefined formulas. I used some custom JavaScript code in my application but that was by just surfing online for my requirement. I did have some difficulties as the error occurred due to a typo. My suggestion is to get the code surfing, then paste it into an online compiler before pasting it into the custom code window.
  • Improvement: Improvements like storing and retrieving the details from the cloud, user login screens can be created with authentication, downloading of tickets to the device after getting generated or stored in the device path and good UI improvements can be made.

Conclusion

AppGyver is a very easy way to create applications in short amount of time and efforts. There is definitely some learning curve if you want to create an application with a very good UI. I was able to do this much after watching all Onno Bos’s videos on the You tube channel Curiosity Lab channel. I am looking forward to creating more applications with good responsiveness across all the devices.