Build a Simple Pomodoro Web App

A beginner’s guide

Anh
Better Programming

--

Photo by Tetiana SHYSHKINA on Unsplash

In our overly connected, notification-filled world, attention seems to be a currency, one that is too easily wasted and yet equally difficult to attain. Having been a learner all of my life, I can attest that the biggest roadblock to my progress in any learning area is distraction. After all, there always seem to be endless cat videos waiting to be indulged, photos of acquaintances to scroll past, emails to glimpse, notification bells to click… You get the drill.

What had helped my brain overcome the curse of divided attention brought on by this incessant technological noise is a simple time management technique by the name of Pomodoro, credited to Francesco Cirillo. The process roughly looks something like this: 1) choose a task, 2) set a timer to 25 minutes, 3) dedicate those 25 minutes to focusing on the task and the task only, 4) take a brief break, 5) rinse and repeat.

When I started learning how to code not too long ago, I knew that a simple app that makes use of the Pomodoro technique was on my list of things to attempt. The process of creating this app taught me a lot about how to manipulate the document object model, how to recognize events, and how to create dynamic changes on the browser, all without a page refresh. Check out a brief demo of the app below.

The styling of the app is credited to the talented Donat Pllana. While styling is so important in making your app presentable and user-friendly, for the sake of time, I will only be guiding you through how I created the functionality for this single-page app. You can access the source code via CodePen. Feel free to follow along.

The Planning Process: User Stories

To start, I brainstormed user stories, which are simple descriptions of my app’s features from the perspective of a user. As a user, I want to:

  1. Be able to go to the app’s page and see displayed several options of focus minutes to choose from
  2. See a countdown timer displayed after clicking on a focus minute option
  3. Be able to cancel my focus session
  4. Be rewarded with a random inspirational music video when I successfully completed my focus session
  5. Have the option of either completing another focus session or taking a five-minute break

The Starting HTML: See the Minute Options

My index.html file to start looks like this:

I created elements to house the following items: a main header with the app’s name, a description, a countdown, a cancel button, a video, focus minute buttons, and a take-a-break option. I assigned unique IDs to each element, to easily refer back to them later, and also wrapped them in <div> containers to make for easier styling. As a default, I hid the cancel button and the option to “take a break.” I made sure to add “defer” when linking to my index.js file, to ensure that the HTML loads first before any JS code is run.

The ID of each minute button and the take-break span is set to the corresponding minute. The ID will be passed into a function later that is responsible for setting the appropriate starting time. I initially set the ID of minute button 25 to 0.05, to avoid waiting a whole 25 minutes each time to test my app.

Right now the user could see the following:

User Story 1: Completed.

See a Countdown Timer Displayed

When a user clicks on a focus minute option, a countdown timer should display, starting at that specified minute. To make this happened, I made use of event delegation. First, I created variables and assigned to them stable elements I selected from the DOM. This allows me to easily refer back to them later in my code.

Next, I added an event listener to the selectionContainer, calling a function called renderCountdown(). Effectively, I am telling the browser that if the thing I clicked on in the selectionContainer happens to be an element with a class called set-time, to start the countdown.

With the use of helper functions hideElements() and unhideElements(), I am able to easily display what I want the user to see. These functions make use of rest parameters, which allow you to pass in an unknown number of arguments.

Next comes the meat of the app’s functionality. startCountdown() takes in a minute variable in form of an integer and displays in the countdownContainer a changing countdown clock.

First, I wrote the logic that will display the appropriate countdown time, making use of setInterval(), which essentially will run any callback function you pass into it for a specified number of milliseconds. (In this case, we tell it to make the totalTimeInSeconds go down by 1 for each second that has passed). The user now sees this:

User Story 2: Completed. Next, two options present themselves: if the timer reaches 0 and if the user clicks the Cancel button. In either case, the countdown interval should stop, and either a music video should render or the user is taken back to the start.

Cancel the Session

If the user cancels the session, the function renderBackToStart() is called. This function once more makes use of helpers hideElements() and unhideElements() to make it so that the user sees the following displayed once again:


function renderBackToStart() {
hideElements(countdownContainer, cancelContainer, videoContainer, takeBreak);
unhideElements(description, selectionContainer, timeButtonsContainer);
}

User Story 3: Completed.

What Doesn’t Kill You Makes You Stronger

If the user successfully completes the session, we call the renderVideo() function, which takes a random video URL (with specified start time and autoplay parameters attached) from an array of URLs and attaches that to the videoContainer using iframe. Yes, one of the songs is beloved Kelly Clarkson’s Stronger. How’s that for a boost of congratulatory motivation?

This function also makes use of hideElement() and unhideElement() to display options for the user to either start another session or take a five-minute break.

What the user sees:

User Stories 4 and 5: Completed. Boom and boom.

Through working on this app, I learned:

  1. to manipulate the DOM through use of .querySelector(), .addEventListener(), .setInterval(), among other methods
  2. to create helper functions and as much as possible, to delegate a single responsibility to each function
  3. to use ES6 syntax, such as rest parameters and arrow function syntax

Thanks for reading ’til the end. I hope this was helpful. Here’s to continual learning despite distractions in our way!

--

--