Highcharts - Covid-19 Dashboard

author(s): Torstein Hønsi

by Torstein Hønsi

HTML

<script src="https://code.highcharts.com/7/highcharts.js"></script>
<script src="https://code.highcharts.com/7/modules/data.js"></script>
<script src="https://code.highcharts.com/7/modules/series-label.js"></script>
<script src="https://code.highcharts.com/maps/7/modules/map.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/world.js"></script>


<!-- Flag sprites service provided by Martijn Lafeber, https://github.com/lafeber/world-flags-sprite/blob/master/LICENSE -->
<link rel="stylesheet" type="text/css" href="//github.com/downloads/lafeber/world-flags-sprite/flags32.css" />

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">


<div class="container-fluid">

    <div class="btn-group btn-group-toggle" style="margin-bottom: 1rem">
        <label class="btn btn-outline-primary active">
            <input type="radio" name="source" id="confirmed" autocomplete="off"> Confirmed
        </label>
        <label class="btn btn-outline-primary">
            <input type="radio" name="source" id="deaths" autocomplete="off" checked> Deaths
        </label>
    </div>
    <div class="row">
        <div class="col-12 col-md-6">
            <div class="card">
                <div class="card-header" id="map-header">
                </div>
                <div class="card-body" id="container"></div>
            </div>
        </div>
        <div class="col-12 col-md-6" id="info">
            <div class="card">
                <div class="card-header">
                    <span class="f32"><span id="flag"></span></span>
                    <span class="header-text"></span>
                </div>
                <div class="card-header subheader">
                    Click countries to view history
                </div>
                <div class="card-body" id="country-chart">
               ...

CSS

.container-fluid {
    margin-top: 10px;
}
#info .f32 .flag {
    position: absolute;
    top: 8px;
}

.clearfix {
    clear: both;
}
.card-header.subheader {
    font-size: 0.9rem;
    color: rgba(0, 0, 0, 0.75);
    background-color: transparent;
    border-bottom: none;
}
.card {
    height: 80vh;
    min-height: 400px;
    margin-bottom: 1em;
}

@media screen and (max-width: 780px) {
    .card {
        max-height: 400px;
    }
    .col-12 {
        padding-left: 2px !important;
        padding-right: 2px !important;
    }
}

JavaScript

let countries;
let population;

let mapChart;
let countryChart;

const getConfig = type => ({
    confirmed: {
        day0Value: 200,
        header: 'Confirmed Covid-19 Cases',
        name: 'Confirmed cases',
        valueSuffix: 'confirmed cases'
    },
    deaths: {
        day0Value: 10,
        header: 'Deaths caused by Covid-19',
        name: 'Deaths',
        valueSuffix: 'deaths'
    }
}[type]);

const createMap = (type = 'confirmed') => {

    const config = getConfig(type);

    document.getElementById('map-header').innerHTML = config.header;

    // Add lower case codes to the data set for inclusion in the tooltip.pointFormat
    const mapData = Highcharts.geojson(Highcharts.maps['custom/world']);
    const populationByName = {};
    mapData.forEach(function (country) {
        country.id = country.properties['hc-key']; // for Chart.get()
        country.flag = country.id.replace('UK', 'GB').toLowerCase();

        const pop = population.find(
            c => country.properties['hc-key'].toUpperCase() === c.code
        );
        populationByName[country.name] = pop && pop.z || null;
    });

    // Names used in Highcharts Map Collection
    countries['United States of America'] = countries.US;
    countries['South Korea'] = countries['Korea, South'];
    countries['Czech Republic'] = countries.Czechia;

    let maxValue = 0;
    const data = Object.keys(countries).map(name => {
        const country = countries[name];
        const total = country[country.length - 1][type];
        if (populationByName[name]) {
            const value = total / populationByName[name];
            if (populationByName[name] > 1000) {
                maxValue = Math.max(value, maxValue);
            }
            return { name, value, total };
        }
        return { name, value: null };
    });


    // Initiate the map chart
    if (!mapChart) {
        mapChart = Highcharts.mapChart('container', {

            chart: {
                spacingLeft: 1,
       ...