In this article, we will be building a web-based COVID 19 tracker using HTML, CSS, and Javascript, which tracks the coronavirus cases in the World for the last three months and shows it in a line graph. The project is pretty easy and straightforward. You can create a COVID tracker and show it off to your friends!
Things we'll implement in building this tracker are
- 👨🍳 API
- 🤞 Promises
- 🅱 Bootstrap
- 📉 ChartJS
- 🧠 Brain!
File Structure for the App:
COVID Tracker App
index.html
styles.css
scripts.js
So, let's start.
🦴 Creating the Markup
Our HTML file doesn't contain a lot of code. The only necessary thing we need in the HTML except the boilerplate is the Canvas. The canvas is used by the ChartJS library(which we'll see later) to create a chart.
HTML Markup:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<title>Track Covid Tonight</title>
</head>
<body>
<div class="container">
<h1 class="text-center mt-4 heading">Track Covid Tonight</h1>
<canvas id="myChart"></canvas>
</div>
<div class="myList"></div>
<script src="./scripts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
</body>
</html>
As you can see, our HTML file contains the bootstrap CSS file, a local styles.css
file, and the most important scripts.js
file. We also need the ChartJS library to display the chart. We have used CDNs(content delivery networks) for bootstrap and the Chart.
The markup has an h1
element which shows the heading and a canvas that renders the chart. We've enclosed both the h1 and the canvas inside the bootstrap class called the container. Now let's see our styles.css
file.
🎨Adding Styles
styles.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
}
If you want to style the app with your own styles, you can do so. I'd love to see your designs. However, I've kept the app minimal. Our styles.css
file resets the default styles and adds height to the body element. We are using CSS vh
unit which represents the viewport height. We are setting to 100vh
which means the body will cover the complete viewport.
🤴 Adding JavaScript Functions
Now, let's jump to the most important file. The scripts.js
file. Our scripts.js
file contains all the necessary codes to fetch and display the data.
scripts.js
const api = 'https://disease.sh/v3/covid-19/historical/all?lastdays=90';
const getData = async () => {
const response = await fetch(`${api}`);
if (response.ok) {
return await response.json();
} else {
return Promise.reject(response.status);
}
};
const result = getData();
result
.then((data) => {
let date = Object.keys(data.cases);
let total = Object.values(data.cases);
let deaths = Object.values(data.deaths);
let recovered = Object.values(data.recovered);
var ctx = document.getElementById('myChart').getContext('2d');
let myChart = new Chart(ctx, {
type: 'line',
data: {
labels: date,
datasets: [
{
label: 'Total Cases',
data: total,
borderColor: 'rgba(255, 99, 132)',
fill: false,
},
{
label: 'Recovered Cases',
data: recovered,
borderColor: 'rgba(153, 102, 255, 1)',
fill: false,
},
{
label: 'Deaths',
data: deaths,
borderColor: 'rgba(75, 192, 192, 1)',
fill: false,
},
],
},
options: {
scales: {
yAxes: [
{
scaleLabel: {
display: true,
labelString: 'Numbers in Thousands',
},
},
],
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'Date(DD/MM/YYYY)',
},
},
],
},
title: {
display: true,
text: `Coronovirus Cases in India for Last Three Months`,
},
},
});
})
.catch((error) => {
console.log('Error: ', error);
});
Don't get scared. The file looks scary, but it isn't. We'll understand the file by breaking in into parts.
Let's start at the top. We will use an API called disease.sh to fetch our data. I hope you know what an API is? API stands for Application Programming Interface. An API works as a waiter between the client and the server to put it in easy words. We ask for data from the server using the API, and the server returns our data through the API. It works as an intermediary.
We'll use the disease.sh to fetch coronavirus cases for the last 90 days. To fetch data from a date range, the API uses the below endpoint
https://disease.sh/v3/covid-19/historical/all?lastdays=NO-OF-DAYS
We are setting the number of days to 90. Then we are fetching the data using an async function. First, let's see how the data looks like,
I've reduced the days to 10 to make it look cleaner here. This data might look cluttered in your browser. I've used a JSON formatter extension to look it cleaner. So, the API returns us three objects, i.e., cases, deaths and recovered. Each of the objects contains a key-value pair of date and numbers. The numbers represent the number of cases, deaths and recoveries. I think you get the idea. Now let's see how we fetch the data using the API.
const api = 'https://disease.sh/v3/covid-19/historical/all?lastdays=90';
const getData = async () => {
const response = await fetch(`${api}`);
if (response.ok) {
return await response.json();
} else {
return Promise.reject(response.status);
}
};
We've added basic error handling to the function. If the response.ok
is true, only then our promise will resolve. Otherwise, it'll reject and return an error. Also, we are using JavaScript template literals
to fetch the API in our getData
function. After creating the function we will be storing the data returned in a variable called result
. Because the function will also return a promise, we have to handle it using a then
statement. If you are not comfortable with JavaScript Promises, you can check the MDN docs.
const result = getData();
result
.then((data) => {
let date = Object.keys(data.cases);
let total = Object.values(data.cases);
let deaths = Object.values(data.deaths);
let recovered = Object.values(data.recovered);
};
This is the first part of our then
statement. First, we are storing the dates in an array called date
. We are sorting the data in arrays because ChartJS supports arrays. The Object.keys
method returns an array containing the key properties from an object. We are targeting the keys because the API returns the values in a key-value
pair of dates and cases. Then we are targeting the total cases, deaths and recoveries similarly and storing them to corresponding variables. You can console.log
the values to see how the arrays look.
We are almost done with the data. The only thing which is left now is visualizing the data. To visualize, we'll be using a popular data visualization library called Chart.js. It is a lightweight library which can make it easy to visualize data in popular formats like a bar chart, line chart, pie chart and more. We'll be using the line chart here.
Let's see the myChart
function.
var ctx = document.getElementById('myChart').getContext('2d');
let myChart = new Chart(ctx, {
type: 'line',
data: {
labels: date,
datasets: [
{
label: 'Total Cases',
data: total,
borderColor: 'rgba(255, 99, 132)',
fill: false,
},
{
label: 'Recovered Cases',
data: recovered,
borderColor: 'rgba(153, 102, 255, 1)',
fill: false,
},
{
label: 'Deaths',
data: deaths,
borderColor: 'rgba(75, 192, 192, 1)',
fill: false,
},
],
},
options: {
scales: {
yAxes: [
{
scaleLabel: {
display: true,
labelString: 'Number of Cases',
},
},
],
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'Date(DD/MM/YYYY)',
},
},
],
},
title: {
display: true,
text: `Coronavirus Cases in the World for 90 Days`,
},
},
});
The first thing we are doing here is, we are targeting our canvas
which has an ID of myChart
. The getContext
gives access to the canvas tags 2D drawing functions. Then using the Chart constructor, we're creating a function that contains all the necessary configurations for the chart. The type:'line'
specifies the type of chart. The data
object holds all the datasets
, labels
and other data related configurations. We are passing our date variable as the label for our chart using labels: date
. The datasets
are an array of objects which hold the label, data, and colors for each line. There are a lot of other configurations available. But to keep this article simple we are using minimal options. You can check their documentation to get an idea about available options here. After the data
object, we are setting up a few options for the look. The labels for x and y axes are set using the yAxes
and xAxes
objects. And the title for the chart is setup using the title
object. We have completed our code. The last thing left is to catch any error. The catch
statement is used in promises to catch errors. For this app, we'll catch the error and console.log
it into the console.
.catch((error) => {
console.log('Error: ', error);
});
After following all the steps, our app will look like this,
You can check the live version of the app here. And to see the source code, visit here
.
I hope you enjoyed building this tracker. I've tried to keep it simple. Now try building your own COVID tracker and share it with us.