Create Simple COVID-19 Tracker With Angular 10 And Material Design

Introduction

 
In this pandemic period, many of us are suffering due to Corona virus. I have decided to create a simple app to track the important details of Covid-19 and show this data in the dashboard. This app will provide an option to choose a country and display the data of that particular country easily. We will also display the highest recovered top 10 country details along with highest confirmed and highest death details.
 

API used for getting Covid-19 data

 
Create Simple COVID-19 Tracker With Angular 10 And Material Design
 
We are using https://covid19api.com/ to fetch the latest data for Covid-19 affected people. There are various API methods available in this application but for our purpose, we are using only one API method, https://api.covid19api.com/summary This method will provide all the global summary data along with summary of each active countries. These data are currently sufficient for our application. I am not claiming any data accuracy. This is only for learning purpose.
 

Create Angular 10 application using latest Angular CLI

 
We can use below CLI command to create new Angular 10 app.
 
ng new covid19-tracker
 
After loading all the node packages and dependencies, we can add Angular Material to the project.
 
ng add @angular/material
 
We can choose the default theme for material design and choose other default options.
 
Open the source code in Visual Studio Code.
 
We must import references for HttpClientModule, MatCardModule, and MatSelectModule modules in app.module.
 
app.module.ts
  1. import { BrowserModule } from '@angular/platform-browser';  
  2. import { NgModule } from '@angular/core';  
  3.   
  4. import { AppComponent } from './app.component';  
  5. import { BrowserAnimationsModule } from '@angular/platform-browser/animations';  
  6.   
  7. import { HttpClientModule } from '@angular/common/http';  
  8. import { MatCardModule } from '@angular/material/card';  
  9. import { MatSelectModule } from '@angular/material/select';  
  10.   
  11. @NgModule({  
  12.   declarations: [  
  13.     AppComponent  
  14.   ],  
  15.   imports: [  
  16.     BrowserModule,  
  17.     BrowserAnimationsModule,  
  18.     HttpClientModule,  
  19.     MatCardModule,  
  20.     MatSelectModule  
  21.   ],  
  22.   providers: [],  
  23.   bootstrap: [AppComponent]  
  24. })  
  25. export class AppModule { }  
Create a data service to fetch data from Covid-19 API application.
 
data.service.ts
  1. import { Injectable } from '@angular/core';  
  2. import { HttpClient } from '@angular/common/http';  
  3. import { Observable } from 'rxjs';  
  4.   
  5. @Injectable({  
  6.   providedIn: 'root'  
  7. })  
  8. export class DataService {  
  9.   
  10.   constructor(private http: HttpClient) { }  
  11.   private url: string = "https://api.covid19api.com/summary";  
  12.   
  13.   getData(): Observable<any> {  
  14.     return this.http.get(this.url)  
  15.       .pipe((response) => response);  
  16.   }  
  17. }  
In above service, we are fetching the summary method from Covid-19 API application.
 
Create Simple COVID-19 Tracker With Angular 10 And Material Design
 
Above is the sample response from that API method. This response has two parts. Global summary part and country wise summary part. This is the entire country data as an array.
 
We can create some model classes inside the model.ts file.
 
model.ts
  1. export class SummaryData {  
  2.     Global: GlobalData;  
  3.     Countries: Array<CountryData>;  
  4.     Date: Date;  
  5. }  
  6.   
  7. export class GlobalData {  
  8.     NewConfirmed: number;  
  9.     NewDeaths: number;  
  10.     NewRecovered: number;  
  11.     TotalConfirmed: number;  
  12.     TotalDeaths: number;  
  13.     TotalRecovered: number  
  14. }  
  15.   
  16. export class CountryData extends GlobalData {  
  17.     Country: string;  
  18.     CountryCode: string;  
  19.     Date: Date;  
  20.     Slug: string  
  21. }  
We have created three model classes SummaryData, GlobalData, and CountryData.
 
We can modify the app.component.ts file with below code.
 
app.component.ts
  1. import { Component, OnInit } from '@angular/core';  
  2. import { SummaryData, CountryData } from './models';  
  3. import { DataService } from './data.service';  
  4. import { DatePipe } from '@angular/common';  
  5. @Component({  
  6.   selector: 'app-root',  
  7.   templateUrl: './app.component.html',  
  8.   styleUrls: ['./app.component.css'],  
  9.   providers: [DatePipe]  
  10. })  
  11. export class AppComponent implements OnInit {  
  12.   title = 'covid19-tracker';  
  13.   summaryData: SummaryData;  
  14.   indiaData: CountryData;  
  15.   selectedCountryData: CountryData;  
  16.   highlyConfirmedData: Array<CountryData>;  
  17.   highlyDeathData: Array<CountryData>;  
  18.   highlyRecoveredData: Array<CountryData>;  
  19.   currentDate: string;  
  20.   
  21.   constructor(private service: DataService, private datePipe: DatePipe) { }  
  22.   
  23.   ngOnInit() {  
  24.     let date = new Date();  
  25.     this.currentDate = this.datePipe.transform(date,'dd-MMM-yyyy');  
  26.     this.getAllData();  
  27.   }  
  28.   
  29.   getAllData() {  
  30.     this.service.getData().subscribe(  
  31.       response => {  
  32.         this.summaryData = response;  
  33.         this.getIndiaData();  
  34.         this.getSortedData();  
  35.       }  
  36.     )  
  37.   }  
  38.   
  39.   getIndiaData() {  
  40.     this.indiaData = this.summaryData.Countries.find(x => x.Slug == "india");  
  41.   }  
  42.   
  43.   getSortedData() {  
  44.     let data = JSON.parse(JSON.stringify(this.summaryData.Countries));  
  45.     this.highlyConfirmedData = data.sort((a, b) => b.TotalConfirmed - a.TotalConfirmed).slice(0, 10);  
  46.     this.highlyDeathData = data.sort((a, b) => b.TotalDeaths - a.TotalDeaths).slice(0, 10);  
  47.     this.highlyRecoveredData = data.sort((a, b) => b.TotalRecovered - a.TotalRecovered).slice(0, 10);  
  48.   }  
  49. }  
We have fetched the global summary data from data service and populated other data for our application. I have used very simple logic for this.
 
We can modify the app.component.html file with below code snippets.
 
app.component.html
  1. <div style="width: 1200px;">  
  2.   <div class="same-row" style="width: 550px;">  
  3.       <img src="../assets/CovidTracker.PNG">  
  4.   </div>  
  5.   <div class="same-row" style="font-weight: bold;">  
  6.     As on : {{currentDate}}  
  7.   </div>  
  8.   <div class="same-row">  
  9.       <mat-form-field appearance="fill" style="width: 300px;">  
  10.           <mat-label>Choose a Country</mat-label>  
  11.           <mat-select [(value)]="selectedCountryData">  
  12.               <mat-option *ngFor="let country of summaryData?.Countries" [value]="country">{{country.Country}}  
  13.               </mat-option>  
  14.           </mat-select>  
  15.       </mat-form-field>  
  16.   </div>  
  17. </div>  
  18. <div>  
  19.   <div class="same-row">  
  20.       <mat-card class="covid-card">  
  21.           <mat-card-header>  
  22.               <div mat-card-avatar>  
  23.                   <img  
  24.                       src="https://www.sanlam.co.uk/web/media/media/vectors%2018/globe_light_blue_rgb.png?width=32&height=32&mode=crop">  
  25.               </div>  
  26.               <mat-card-title>Global Summary</mat-card-title>  
  27.               <mat-card-subtitle>Total Countries</mat-card-subtitle>  
  28.           </mat-card-header>  
  29.           <mat-card-content>  
  30.               <table>  
  31.                   <tr>  
  32.                       <td>  
  33.                           New Recovered  
  34.                       </td>  
  35.                       <td>  
  36.                           {{summaryData?.Global?.NewRecovered | number}}  
  37.                       </td>  
  38.                   </tr>  
  39.                   <tr>  
  40.                       <td>  
  41.                           Total Recovered  
  42.                       </td>  
  43.                       <td>  
  44.                           {{summaryData?.Global?.TotalRecovered | number}}  
  45.                       </td>  
  46.                   </tr>  
  47.                   <tr>  
  48.                       <td>  
  49.                           New Confirmed  
  50.                       </td>  
  51.                       <td>  
  52.                           {{summaryData?.Global?.NewConfirmed | number}}  
  53.                       </td>  
  54.                   </tr>  
  55.                   <tr>  
  56.                       <td>  
  57.                           Total Confirmed  
  58.                       </td>  
  59.                       <td>  
  60.                           {{summaryData?.Global?.TotalConfirmed | number}}  
  61.                       </td>  
  62.                   </tr>  
  63.                   <tr>  
  64.                       <td>  
  65.                           New Deaths  
  66.                       </td>  
  67.                       <td>  
  68.                           {{summaryData?.Global?.NewDeaths | number}}  
  69.                       </td>  
  70.                   </tr>  
  71.                   <tr>  
  72.                       <td>  
  73.                           Total Deaths  
  74.                       </td>  
  75.                       <td>  
  76.                           {{summaryData?.Global?.TotalDeaths | number}}  
  77.                       </td>  
  78.                   </tr>  
  79.               </table>  
  80.           </mat-card-content>  
  81.       </mat-card>  
  82.   </div>  
  83.   
  84.   <div class="same-row">  
  85.       <mat-card class="covid-card">  
  86.           <mat-card-header>  
  87.               <div mat-card-avatar>  
  88.                   <img src="https://www.countryflags.io/IN/shiny/32.png">  
  89.               </div>  
  90.               <mat-card-title>Country Summary</mat-card-title>  
  91.               <mat-card-subtitle>India</mat-card-subtitle>  
  92.           </mat-card-header>  
  93.           <mat-card-content>  
  94.               <table>  
  95.                   <tr>  
  96.                       <td>  
  97.                           New Recovered  
  98.                       </td>  
  99.                       <td>  
  100.                           {{indiaData?.NewRecovered | number}}  
  101.                       </td>  
  102.                   </tr>  
  103.                   <tr>  
  104.                       <td>  
  105.                           Total Recovered  
  106.                       </td>  
  107.                       <td>  
  108.                           {{indiaData?.TotalRecovered | number}}  
  109.                       </td>  
  110.                   </tr>  
  111.                   <tr>  
  112.                       <td>  
  113.                           New Confirmed  
  114.                       </td>  
  115.                       <td>  
  116.                           {{indiaData?.NewConfirmed | number}}  
  117.                       </td>  
  118.                   </tr>  
  119.                   <tr>  
  120.                       <td>  
  121.                           Total Confirmed  
  122.                       </td>  
  123.                       <td>  
  124.                           {{indiaData?.TotalConfirmed | number}}  
  125.                       </td>  
  126.                   </tr>  
  127.                   <tr>  
  128.                       <td>  
  129.                           New Deaths  
  130.                       </td>  
  131.                       <td>  
  132.                           {{indiaData?.NewDeaths | number}}  
  133.                       </td>  
  134.                   </tr>  
  135.                   <tr>  
  136.                       <td>  
  137.                           Total Deaths  
  138.                       </td>  
  139.                       <td>  
  140.                           {{indiaData?.TotalDeaths | number}}  
  141.                       </td>  
  142.                   </tr>  
  143.               </table>  
  144.           </mat-card-content>  
  145.       </mat-card>  
  146.   </div>  
  147.   
  148.   <div class="same-row" *ngIf="selectedCountryData!=undefined">  
  149.       <mat-card class="covid-card">  
  150.           <mat-card-header>  
  151.               <div mat-card-avatar>  
  152.                   <img src="https://www.countryflags.io/{{selectedCountryData.CountryCode}}/shiny/32.png">  
  153.               </div>  
  154.               <mat-card-title>Country Summary</mat-card-title>  
  155.               <mat-card-subtitle>{{selectedCountryData.Country}}</mat-card-subtitle>  
  156.           </mat-card-header>  
  157.           <mat-card-content>  
  158.               <table>  
  159.                   <tr>  
  160.                       <td>  
  161.                           New Recovered  
  162.                       </td>  
  163.                       <td>  
  164.                           {{selectedCountryData?.NewRecovered | number}}  
  165.                       </td>  
  166.                   </tr>  
  167.                   <tr>  
  168.                       <td>  
  169.                           Total Recovered  
  170.                       </td>  
  171.                       <td>  
  172.                           {{selectedCountryData?.TotalRecovered | number}}  
  173.                       </td>  
  174.                   </tr>  
  175.                   <tr>  
  176.                       <td>  
  177.                           New Confirmed  
  178.                       </td>  
  179.                       <td>  
  180.                           {{selectedCountryData?.NewConfirmed | number}}  
  181.                       </td>  
  182.                   </tr>  
  183.                   <tr>  
  184.                       <td>  
  185.                           Total Confirmed  
  186.                       </td>  
  187.                       <td>  
  188.                           {{selectedCountryData?.TotalConfirmed | number}}  
  189.                       </td>  
  190.                   </tr>  
  191.                   <tr>  
  192.                       <td>  
  193.                           New Deaths  
  194.                       </td>  
  195.                       <td>  
  196.                           {{selectedCountryData?.NewDeaths | number}}  
  197.                       </td>  
  198.                   </tr>  
  199.                   <tr>  
  200.                       <td>  
  201.                           Total Deaths  
  202.                       </td>  
  203.                       <td>  
  204.                           {{selectedCountryData?.TotalDeaths | number}}  
  205.                       </td>  
  206.                   </tr>  
  207.               </table>  
  208.           </mat-card-content>  
  209.       </mat-card>  
  210.   </div>  
  211. </div>  
  212. <div>  
  213.   <div class="same-row table-data">  
  214.       <p style="font-weight: bold; color: darkgreen; font-size: large;">Highest Recovered Cases</p>  
  215.       <table>  
  216.           <tr>  
  217.               <td style="font-weight: bold;">  
  218.                   Sl.No.  
  219.               </td>  
  220.               <td style="font-weight: bold;">  
  221.                   Country  
  222.               </td>  
  223.               <td style="font-weight: bold;">  
  224.                   Total Recovered  
  225.               </td>  
  226.           </tr>  
  227.           <tr *ngFor="let country of highlyRecoveredData; let i=index">  
  228.               <td>  
  229.                   {{i+1}}  
  230.               </td>  
  231.               <td>  
  232.                   {{country.Country}}  
  233.               </td>  
  234.               <td>  
  235.                   {{country.TotalRecovered | number}}  
  236.               </td>  
  237.           </tr>  
  238.       </table>  
  239.   </div>  
  240.   <div class="same-row table-data">  
  241.       <p style="font-weight: bold; color:gray; font-size: large;">Highest Confirmed Cases</p>  
  242.       <table>  
  243.           <tr>  
  244.               <td style="font-weight: bold;">  
  245.                   Sl.No.  
  246.               </td>  
  247.               <td style="font-weight: bold;">  
  248.                   Country  
  249.               </td>  
  250.               <td style="font-weight: bold;">  
  251.                   Total Confirmed  
  252.               </td>  
  253.           </tr>  
  254.           <tr *ngFor="let country of highlyConfirmedData; let i=index">  
  255.               <td>  
  256.                   {{i+1}}  
  257.               </td>  
  258.               <td>  
  259.                   {{country.Country}}  
  260.               </td>  
  261.               <td>  
  262.                   {{country.TotalConfirmed | number}}  
  263.               </td>  
  264.           </tr>  
  265.       </table>  
  266.   </div>  
  267.   <div class="same-row table-data">  
  268.       <p style="font-weight: bold; color: indianred; font-size: large;">Highest Death Cases</p>  
  269.       <table>  
  270.           <tr>  
  271.               <td style="font-weight: bold;">  
  272.                   Sl.No.  
  273.               </td>  
  274.               <td style="font-weight: bold;">  
  275.                   Country  
  276.               </td>  
  277.               <td style="font-weight: bold;">  
  278.                   Total Deaths  
  279.               </td>  
  280.           </tr>  
  281.           <tr *ngFor="let country of highlyDeathData; let i=index">  
  282.               <td>  
  283.                   {{i+1}}  
  284.               </td>  
  285.               <td>  
  286.                   {{country.Country}}  
  287.               </td>  
  288.               <td>  
  289.                   {{country.TotalDeaths | number}}  
  290.               </td>  
  291.           </tr>  
  292.       </table>  
  293.   </div>  
  294. </div>  
We have used Angular material select component to list the country name and also used material card to display Covid-19 data. We have used some inline styles inside the html file but that is not advisable. I will cleanup this code very soon and remove these inline styles from html file.
 
We can add some css class details inside the app.component.css file.
 
app.component.css
  1. .covid-card {  
  2.     max-width350px;  
  3. }  
  4.   
  5. .same-row {  
  6.     display: inline-block;  
  7.     padding10px;  
  8. }  
  9.   
  10. .table-data {  
  11.     padding10px;  
  12.     margin10px;  
  13. }  
  14.   
  15. table {  
  16.     padding10px;  
  17.     width300px;  
  18.     border1px solid gray;  
  19.     background-color: honeydew;  
  20. }  
  21.   
  22. tr {  
  23.     margin10px;  
  24.     padding10px;  
  25. }  
  26.   
  27. td {  
  28.     height30px;  
  29.     vertical-aligncenter;  
  30.     border1px dotted gray;  
  31. }  
We have successfully built our Covid-19 tracker application in short time. We can run the application now.
 
Create Simple COVID-19 Tracker With Angular 10 And Material Design 
 
We have showed Global summary, Indian country summary along with top 10 highest recovered, highest confirmed and highest death cases.
 
User can choose the country name from the material list box.
 
Create Simple COVID-19 Tracker With Angular 10 And Material Design
 
After choosing a country name, we can get the data for that particular country in below card.
 
Create Simple COVID-19 Tracker With Angular 10 And Material Design
 
I have deployed this application to Google firebase and you can use this LIVE app to track Covid-19 data.
 

Conclusion


In this post, we have seen how to create a simple Covid-19 tracker app with Angular 10 using Material design. We have used https://covid19api.com/ free API service to fetch live data. We have provided an option to choose any country name and get data of that country. We have also provided the highest 10 recovered, highest confirmed, and highest death cases. If anybody is interested, we can tweak this application with more features like data analysis using some charts as well. Please feel free to provide the feedback about this application.