<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Covid-19 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Covid-19 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:21:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/covid-19/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How I Learned Web Development During the COVID-19 Lockdown and Built a Website Thousands of People Are Using ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Naor In early March of 2020 my company asked staff to work from home because of the spread of Coronavirus. At first, the change from a traditional office setting to remote work was jarring: my very small New York City apartment didn’t enable ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-i-got-hooked-creating-a-website-in-a-new-market/</link>
                <guid isPermaLink="false">66d45d8fcc7f04d2549a3710</guid>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ remote work ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 03 Aug 2020 17:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/website-launch-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Naor</p>
<p>In early March of 2020 my company asked staff to work from home because of the spread of Coronavirus.</p>
<p>At first, the change from a traditional office setting to remote work was jarring: my very small New York City apartment didn’t enable a comfortable work area in which to write, code, or perform proactive tasks. </p>
<p>Over time I did my best to adjust and, like many of my colleagues, spent time searching for ways to adapt to new routines. </p>
<p>Make the most of the situation, I frequently reminded myself.</p>
<p>Given the prevalence of coronavirus New York, I knew I would be indoors for months on end. This led me to an idea: I challenged myself to learn a new skill. I thought that learning something challenging and different would be enjoyable and a much needed and reliable distraction.</p>
<p>I spent time reflecting on what I wanted to learn. I then conducted research and came up with a short list of skills I thought I could develop during quarantine that met the following criteria:  </p>
<ol>
<li>Learning the skill should be fun</li>
<li>Once acquired, I should be able to use the skill more broadly in my life</li>
<li>The skill should help me build something useful or of value to others</li>
<li>And lastly, I should learn the skill through self-learning online. </li>
</ol>
<p>Given these guideposts, and my circle of competence, I created a list of things I would be interested in diving deeper into. </p>
<p>My initial list included: </p>
<ul>
<li>learning to play the guitar, </li>
<li>becoming a reasonably competent amatuer chef capable of making a diverse array of nutritious meals, </li>
<li>improving upon my very rusty Mandarin skills acquired while studying abroad in China,</li>
<li>building a website - more or less from scratch - to help people, like me, working from home.</li>
</ul>
<p>After consulting with friends and reviewing various online tutorials, I chose to build my first website. Instantly, I was hooked. </p>
<p>I have learned so much along the way and want to now share some of these core lessons with you. </p>
<p>My story is not yet complete as the site that I developed is still growing and I am learning more by the week.</p>
<p>There are many resources online on how to build a website or monetize a blog. This post is not that. </p>
<p>I want to focus on a few higher level topics that I became aware of - and that you should know - before diving deep into a website project of your own.</p>
<h2 id="heading-insight-1-when-building-a-website-build-around-a-topic-you-are-passionate-about">Insight #1: When building a website, build around a topic you are passionate about</h2>
<p>When I started building WFHAdviser.com, I was essentially building an online resource that helped me solve a series of problems that I was acutely aware of. </p>
<p>Even if traffic was minimal, my thinking went, the site would still be useful for me and a few colleagues struggling with basic questions like: </p>
<ul>
<li>How to negotiate new benefits and perks while working remotely? </li>
<li>How to best set up a home office on a budget? </li>
<li>Ways to mitigate stress or maintain a comfortable posture when working in a bedroom?</li>
</ul>
<p>I found the process of creating content for the site deeply rewarding. </p>
<p>Not only was it fun to write on these topics, but I got to learn more about what people cared about and what challenges they were facing in home office environments. </p>
<p>I did qualitative research and called friends and spoke with them about how they were handling remote work. I did quantitative research and looked at search query trends to better understand what people were searching for online.</p>
<p>This process was laborious. Nights and weekends became dedicated to learning more about the work from home space. I translated these learnings into content that I would then share with important people (friends, family, peers) in my life. These people, in turn, shared my site with others.</p>
<p>Getting e-mails and messages from friends of friends or former colleagues about how my blogs helped them successfully work from home accelerated my interest in building more resources, guides, and content that could help these readers.</p>
<p>So if you want to build a website, make sure to start a site in a vertical you care about. Take time to understand what you are building, and why, and ensure your digital fingerprints are across it in detail: take ownership of what the site says, how it looks, and whom it helps.</p>
<p>The flywheel starts with passion. The list of possible niches is infinite. For me it is the work from home space.</p>
<h2 id="heading-insight-2-speed-matters-so-move-quickly">Insight #2: Speed matters, so move quickly</h2>
<p>The first version of the website looked so-so at best. It would be generous to call it a glorified landing page with a few links. The website was missing features and functionality I knew I wanted to include but that I couldn’t complete upon launch. </p>
<p>Some of the content that I wrote needed edits, but I placed these blogs on the site anyway. A few of my links, unfortunately, led to 404 errors.</p>
<p>Why am I candidly sharing the shortcomings of the site at launch? </p>
<p>Because I believe that speed to market matters if you have an obsession with helping users.</p>
<p>Showing a bias towards action and insisting on high standards are not mutually exclusive concepts. You should have a vision for a site and launch it when it's not yet complete knowing that future improvements will yield better results. </p>
<p>From the website's launch in March 2020 until August 2020, I performed roughly 1,000 edits, improvements, and fixes. Had I waited five months to get everything “right” tens of thousands of people would not have gotten their questions answered or learned about strategies to work from home successfully.</p>
<p><em>The flywheel needs initial momentum to get moving.</em></p>
<h2 id="heading-insight-3-earn-the-trust-of-users">Insight #3: Earn the trust of users</h2>
<p>My final key learning is that users need to trust a website (and the site’s authors) in order to spend time on its pages and absorb the site’s content. </p>
<p>When users first came to my site, I noticed high bounce rates. Given how empty the site was, this was not surprising.</p>
<p>But after ample work and site improvements, people actually spent more time looking at the guides I wrote and the resources I cultivated. My attention to detail increased as the titles of my pieces became indexed on Google. </p>
<p>I found the experience of earning user trust deeply rewarding. I reviewed three metrics weekly: how much time was spent on each page, website abandonment rates, and bounce rates. </p>
<p>As I made general and specific website improvements, these operational metrics improved. I replaced large image files with smaller ones to reduce latency and load times. I optimized the site for speed.</p>
<p>I became obsessed not with how many people visited the site but the amount of time they spent there. I used time on site as a proxy for how useful and helpful my content was. As my visitors demonstrated to me that their experiences were getting better, I knew I was headed in the right direction.</p>
<p><em>The flywheel needs trust to turn.</em></p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>Spending long periods of time in quarantine gave me time to develop a newfound skill, website development. This skill has unlocked a new passion (helping people working from home) in a newly emerging vertical (remote work).</p>
<p>A world where people are educated about how to work successfully from home is a world I want to live in - and one that I am on an ongoing mission to create.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What it’s Really Like to Cope with Endless Distractions While Working from Home ]]>
                </title>
                <description>
                    <![CDATA[ By Daniel Borowski Whether or not you have worked remotely before, you’ve likely never had to share your “home office” with your partner and two children.  Before quarantine, a study showed that engineers preferred working from home and felt more pro... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/coding-with-distractions/</link>
                <guid isPermaLink="false">66d45e02a3a4f04fb2dd2e3b</guid>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ focus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ remote work ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 19 May 2020 14:01:46 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/codingwithdistractions.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Daniel Borowski</p>
<p>Whether or not you have worked remotely before, you’ve likely never had to share your “home office” with your partner and two children. </p>
<p>Before quarantine, a study showed that engineers preferred working from home and <a target="_blank" href="https://blog.rescuetime.com/work-from-home-productivity-data/">felt more productive</a> than they were in the office. However, over a month into quarantine, many software developers sharing small spaces are starting to look back at those late nights in the office longingly. </p>
<p>By adopting some realistic tips along with help from supportive employers, developers can regain some focus, return a little bit closer to peak productivity, and achieve a state of mental wellness.</p>
<p>My team at <a target="_blank" href="https://coderbyte.com">Coderbyte</a> surveyed 150+ software developers to better understand how they were coping with social distancing. The results illustrate how many software developers have more time to code and even <a target="_blank" href="https://levelup.gitconnected.com/covid-19-is-giving-software-developers-time-to-hustle-and-work-on-passion-projects-979411212d2b">work on side projects</a>, but many are also struggling to maintain focus and productivity.</p>
<p><img src="https://lh3.googleusercontent.com/Y_U8rSQdzOVxozkgiFkButyPavTinhz-3jrFxCPHWKSp3iWBdahsR78EK7CafGMRD0MD2pcMqHpXHDlnVBsGbapbge12jjtmzM0MqarifWoh2AdkW4O0AmILvoo3I_76BSvP2l11" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://lh6.googleusercontent.com/NzIZz-1WRBU-JcpDs8k9iQWICihBbQwrkKS6yHPsfeEvpyQtS6LULIpqIUFr7bT-T5VPid0W2Xq_4kEOW8mb13AqN4ub5oLIn24m88s3-4IdndLgkJvBrD30cJp1O-PLk5_L6OH3" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We also interviewed a senior software engineer, Geoff Chin, with a wife and two children under the age of four to understand what it really looks like to shelter in place with two full time working parents. </p>
<p>We captured his reactions to the adrenaline-fueled optimism of tips and tricks from other experts below, and then provide recommendations for employers:</p>
<h2 id="heading-how-realistic-is-it-for-developers-coping-with-distractions-to">How realistic is it for developers coping with distractions to...</h2>
<h3 id="heading-ia"> </h3>
<p><a target="_blank" href="https://thewirecutter.com/blog/work-from-home-with-kids/">Set a schedule?</a></p>
<p>Sounds reasonable enough, right? Work is scheduled, school is scheduled, why not quarantine too? Here’s what we learned:</p>
<blockquote>
<p>“The first week we were excited to be together. We had every hour blocked off with time for Legos, lunch, outdoors time, arts and crafts just waiting for the department of education to start online classes.   </p>
<p>After the first week our schedules quickly broke down. The kids were bored easily, our work schedules didn’t align with the kids’ schedules. And then class started. You think Zoom meetings are bad with adults? They are way worse with kids.”</p>
</blockquote>
<p>Since rigid schedules are out of the question, maintain a flexible mindset and split up the day so that one parent is fully available at all times.</p>
<h3 id="heading-signal-to-kids-when-you-cannot-be-interrupted-by-using-physical-separationhttpswwwparentscomparentingworklife-balancehow-to-master-being-a-work-at-home-mom"><a target="_blank" href="https://www.parents.com/parenting/work/life-balance/how-to-master-being-a-work-at-home-mom/">Signal to kids when you cannot be interrupted, by using physical separation</a>?</h3>
<p>As many articles noted, when space is limited this can be difficult. However, even within a 500 square foot apartment, this family has found “tag-teaming” childcare as the best way to make it work. </p>
<blockquote>
<p>“We thought we could work and watch the kids at the same time — not a chance. We invested in proper furniture to <a target="_blank" href="https://www.shrm.org/hr-today/news/hr-news/Pages/For-Better-or-Worse-During-COVID19-Sharing-Telework-Space-.aspx?utm_source=marketo&amp;utm_medium=email&amp;utm_campaign=editorial~HR%20Daily~NL_2020-4-17_HR-Daily&amp;linktext=For-Better-or-Worse-During-COVID-19-Sharing-Telework-Space&amp;mkt_tok=eyJpIjoiT0dJeU9HVXhZemxtWlRVdyIsInQiOiJxYllYbVprU2FrcmlkdVFHRThcLzVtVEw1Mm81MFpJRTloa3loOWp2aU1LRlhXK1lMOU1DWmNYalI2NUJQY2pKYjNJSkZtZXp3WjVVUWdIaEJHUng5clJLWDBYaWUyZlFWM1wvY3hBRHdnSjRoXC9FeGFwalBVb0VDaG54eHV1alowZCJ9">set up workspaces</a> at home so my wife and I can tag-team watching the kids.” </p>
</blockquote>
<h3 id="heading-stockpile-activities-that-dont-require-adult-supervisionhttpswwwfastcompanycom90478087got-kids-try-these-tips-for-working-from-home-while-theyre-with-you"><a target="_blank" href="https://www.fastcompany.com/90478087/got-kids-try-these-tips-for-working-from-home-while-theyre-with-you">Stockpile activities that don’t require adult supervision?</a></h3>
<blockquote>
<p>“All activities need a certain amount of adult supervision when your kids are under four.   </p>
<p>I talked to my employer and let them know early on that my kids are going to be in meetings. I said, ‘I’ll do my best to mute when I can, but I need to be physically with them during the day.’”</p>
</blockquote>
<h3 id="heading-take-time-for-yourselfhttpsthewirecuttercomblogwork-from-home-with-kids"><a target="_blank" href="https://thewirecutter.com/blog/work-from-home-with-kids/">Take time for yourself</a>?</h3>
<p>“That’s a hard question,” he said, when asked about carving out time for himself. Geoff said he started trying some “meditation and yoga stuff” in the morning, but that is quickly interrupted by the kids running around. </p>
<blockquote>
<p>“Time alone is very difficult right now.”</p>
</blockquote>
<h2 id="heading-during-covid-19-supportive-leaders-can">During Covid-19, supportive leaders can...</h2>
<p>Now that you have insight into what it’s like to be a software engineer trying to cope with distractions, how can you show up for your employees knowing the stresses they deal with at home?</p>
<h3 id="heading-reach-out-to-your-peoplehttpsblogrescuetimecomwork-from-home-productivity-data-and-check-up-on-them"><a target="_blank" href="https://blog.rescuetime.com/work-from-home-productivity-data/">Reach out to your people</a> and check up on them.</h3>
<p>You might not know if your employee is having a rough time and it can be difficult to reach out, especially right now. </p>
<p>Demonstrate a high level of <a target="_blank" href="https://www.hrdive.com/news/remote-work-after-coronavirus-pandemic-gartner-research/576286/">emotional intelligence.</a> By being proactive you show that you are available to support them. Be the one to ask “How are you, really?”</p>
<h3 id="heading-allow-periods-of-focused-uninterrupted-timehttpwwwpaulgrahamcommakersschedulehtml-for-your-team-to-work">Allow periods of focused, <a target="_blank" href="http://www.paulgraham.com/makersschedule.html">uninterrupted time</a> for your team to work</h3>
<p>Clearly communicate the expectations for the week and encourage time for focused work. Lead by example and block off hours in your schedule for “heads down work,” encouraging your team to do the same.</p>
<p>Paul Graham refers to this working style as the “<a target="_blank" href="http://www.paulgraham.com/makersschedule.html">Maker’s Schedule</a>.” Unlike business stakeholders, developers are far more productive when they limit the amount of context switching throughout the day. Instead of scheduling meetings throughout the day, block off several hours to accomplish work, uninterrupted.</p>
<p>Remote workers are <a target="_blank" href="https://blog.rescuetime.com/work-from-home-productivity-data/">20% more likely to say they complete all their daily tasks</a> every or most days.</p>
<h3 id="heading-continue-to-develop-your-company-culturehttpsblognamelycomtransition-to-remote-product-development-remotely">Continue to develop your <a target="_blank" href="https://blog.namely.com/transition-to-remote-product-development">company culture</a>, remotely</h3>
<p>All of the fun happy hours, sports leagues, and clubs you used to offer in person? Find a way to keep them alive online.</p>
<p>This could mean offering a stipend for takeout where everyone can eat lunch together, or a virtual happy hour with a game. </p>
<p>Oftentimes this is the only connection your employees have with their peers beyond meetings. Create opportunities to keep your team’s spirits high.</p>
<h3 id="heading-give-permission-to-go-offlinehttpsblogrescuetimecomwork-from-home-productivity-data">Give permission to <a target="_blank" href="https://blog.rescuetime.com/work-from-home-productivity-data/">go offline</a></h3>
<p>This might sound obvious, but with increased workloads and high stress working environments, it is difficult for employees to know when to shut off. Give permission for nights and weekends off and encourage time offline.</p>
<p>People who work from home are 17% more likely to leave work “<a target="_blank" href="https://blog.rescuetime.com/work-from-home-productivity-data/">feeling accomplished</a> about what they set out to do”.</p>
<p>As with everything, there are pros and cons to remote working. While adjusting and re-adjusting to a work from home culture, it is important to understand the impact of quarantine and living through a global pandemic. </p>
<p>Unfortunately no amount of guides and resources is going to be able to help your household adjust quite like trial and error. The good news is that you are not alone. </p>
<p>Continue to try different tricks and tips as the situation evolves and keep the lines of communication open with your manager so you can get the support you need. If you suddenly find yourself with more time, consider <a target="_blank" href="https://medium.com/coderbyte/the-best-coding-challenge-websites-in-2020-2e39f71cf488">practicing your coding skills</a> to level up.</p>
<p>If you are an employer, do not be shy to reach out and check in with your team. They need a steady hand and guidance now more than ever. </p>
<p>Make sure to check our <a target="_blank" href="https://insights.coderbyte.com/covid-19">guide to remote software development during Covid-19</a>, bookmark our continuously updated article with <a target="_blank" href="https://medium.com/coderbyte/how-the-covid-19-pandemic-is-impacting-software-development-hiring-72243f41ac9e">software development dat</a>a, and keep testing out different ways to keep building culture and connection to prioritize the mental and physical health of your company.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Bar Chart Race on COVID-19 Cases in 5 Minutes with Tableau ]]>
                </title>
                <description>
                    <![CDATA[ By Black Raven When you build a bar chart race, you're creating many discrete pages of bar charts and then stringing them together. This is just like how traditional cartoon animation works.  In December 2019, Tableau released version 2020.1 beta wit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-bar-chart-race-on-covid-19-cases-in-tableau/</link>
                <guid isPermaLink="false">66d45dd77df3a1f32ee7f7df</guid>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tableau ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 24 Apr 2020 10:22:16 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9b79740569d1a4ca2c0c.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Black Raven</p>
<p>When you build a bar chart race, you're creating many discrete pages of bar charts and then stringing them together. This is just like how traditional cartoon animation works. </p>
<p>In December 2019, Tableau released version 2020.1 beta with a new Animations feature for dynamic parameters. This means that the <a target="_blank" href="https://public.tableau.com/profile/blackraven#!/vizhome/COVIT-19DailyInfectedCases/COVIT-19DailyInfectedCases">bar chart race</a> below is now very easy to build.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_Rv9h7WGf9JJn43BfqRBKsA.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Watch it in action: [https://www.youtube.com/watch?v=3iZrMkZ3948](https://www.youtube.com/watch?v=3iZrMkZ3948" rel="noopener nofollow)</em></p>
<h2 id="heading-pre-requisites">Pre-requisites</h2>
<p>Download and install <a target="_blank" href="https://public.tableau.com/s/">Tableau Public</a> (version 2020.1.2 onward). It is totally free and has full functionality. The only snag that all of your work can only be published on the Tableau Public server, and not saved locally to your Desktop. This is alright if the data is not sensitive or private.</p>
<p>Download the latest <a target="_blank" href="https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide-2020-04-22.xlsx">COVID-19 data</a> (in *.xlsx format) from the European Centre for Disease Prevention and Control <a target="_blank" href="https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide">website</a>, and rename it using a generic filename like “COVID-19-geographic-distribution-worldwide.xlsx”. You can replace this file with updated data later, using the same filename.</p>
<p>Open the Tableau Public app, and on the "Connect" menu, click on “Microsoft Excel” and select the data file you downloaded. Click on the “Sheet 1” tab at the bottom left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_ejwEHqjx6YjF4jA2vLOapg.png" alt="Image" width="600" height="400" loading="lazy">
<em>Connect Tableau Public to dataset</em></p>
<h2 id="heading-identify-the-quantity-to-race">Identify the Quantity to Race</h2>
<p>There are 2 useful quantities you can choose to race in this dataset:</p>
<ul>
<li>Daily Infected Cases, or </li>
<li>Daily Deaths Cases.</li>
</ul>
<p>To choose the race quantity as daily infected cases, drag “Cases” to Columns.</p>
<p>To label the bar chart with country names, drag “Countries And Territories” to Label.</p>
<p>To have the bars in various colors, drag “Countries And Territories” to Color.</p>
<h2 id="heading-create-rank-for-countries">Create Rank for Countries</h2>
<p>This section requires a simple programming line of code.</p>
<p>Click on Dimensions → drop-down menu → Create Calculated Field.<br>Create a new field “Rank”, and key in the code below:</p>
<p><strong>RANK_UNIQUE(Sum([Cases]))</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_MiqkR2XocHAAj277ErV1jg.png" alt="Image" width="600" height="400" loading="lazy">
<em>To code for Calculated Field “Rank”</em></p>
<p>Click on “Apply” to ensure that calculation is valid, then click “OK”.</p>
<p>Drag “Rank” to Rows.<br>Click on (Rows) Rank → drop down menu → Discrete.<br>Click on (Rows) Rank → drop down menu → Compute Using → “Countries And Territories”.</p>
<h2 id="heading-configure-animation-new-feature-for-version-20201">Configure Animation (New Feature for Version 2020.1)</h2>
<p>To create a snapshot of animation frames, drag “Date Rep” to Pages.<br>Click on (Pages) Date Rep → drop down menu → Exact Date.</p>
<p>Turn on animations, select Format → Animations → On.<br>To set the transition duration: Duration → “1.00 seconds (Slow)”.<br>Close the Animations window by clicking “X”.</p>
<p>Look for a little Animations control which appears when the animations feature is turned on, then click the “forward play” icon. Drag the slider bar to a different date or use the left/right button to choose a date.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_Lc4M3sx0DSp5PrRA6znFjQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Animations control</em></p>
<h2 id="heading-add-simple-customization">Add Simple Customization</h2>
<h3 id="heading-to-improve-colors">To improve colors:</h3>
<p>Click on Label → ensure “Show mark labels” is checked.<br>Click on Color → Edit Colors -&gt; replace similar colors if any.<br>(I have replaced the colors for USA, Spain, Italy)</p>
<p>You can hide the Countries legend card – no need for it anymore.</p>
<h3 id="heading-to-add-additional-labels-for-the-number-of-cases-to-the-bars">To add additional labels for the number of cases to the bars:</h3>
<p>Drag “Cases” to Label.<br>Click on Label → Text → click on “3 dots”. This opens up the label editor.<br>Arrange labels to 1 line only.<br>Underline .<br>Bold , and use red font.<br>Click on “OK”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_cQEuF4ppqaIqpHmvPvkWXQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Label editor</em></p>
<h3 id="heading-to-change-the-name-of-the-sheet">To change the name of the sheet:</h3>
<p>Double-click on “Sheet 1” and change it to “COVID-19 Daily Infected Cases”.</p>
<h3 id="heading-to-change-x-axis-limits">To change X-axis limits:</h3>
<p>Double-click on the X-axis. This brings up the Axis menu. Choose the Range to be “Fixed”: Fixed start=0, Fixed end=40,000.</p>
<h3 id="heading-to-display-only-the-top-15-countries">To display only the top 15 countries:</h3>
<p>Drag “Rank” to Filters → click on “OK”.<br>Click on (Filters) Rank → drop down menu → Compute Using → “Countries And Territories” .<br>Replace “206” with “15”, and click on “OK”.<br>Change the Standard view to “Fit Height”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_n_fm0Q4EtWUhpgi0eizV8A--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>View chart using ‘Fit Height’</em></p>
<h3 id="heading-to-increase-the-font-size-of-the-labels">To increase the font size of the labels:</h3>
<p>Click on Label → Font → drop down menu → change the font size to “15”.</p>
<h3 id="heading-to-add-a-date-label-to-the-chart">To add a date label to the chart:</h3>
<p>Right-click on the empty chart area → Annotate → Area.<br>This brings up the annotation editor.<br>Key in , and increase font size to “20”.<br>Click on “OK”.</p>
<p>Now that the date label was created, resize and move it to the bottom.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/1_YMbjCFpQJIgRUrb7oEbThg.png" alt="Image" width="600" height="400" loading="lazy">
<em>Annotation editor</em></p>
<h2 id="heading-publish-visualization">Publish Visualization</h2>
<p>When you are satisfied with the customization, the visualization is then ready to be published.</p>
<p>Click on File → Save to Tableau Public.</p>
<p>The work is now <a target="_blank" href="https://public.tableau.com/profile/blackraven#!/vizhome/COVIT-19DailyInfectedCases/COVIT-19DailyInfectedCases">published on the Tableau Public server</a>. You can then share it using the available link.</p>
<p>Here’s a video tutorial with a step-by-step guide for the entire process:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/ZnEuq6SHIUI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>A bar chart race becomes very simple to build using the new Animations feature in Tableau Version 2020.1 onward. You can now try it on other country data with date/time series: GDP, Population, Life Expectancy, and so on.</p>
<p>Let your creativity flow!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to add Coronavirus (COVID-19) case statistics to your React map dashboard with Gatsby ]]>
                </title>
                <description>
                    <![CDATA[ Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world? Author's note: Similar to be... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-coronavirus-covid-19-case-statistics-to-your-map-dashboard-in-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66bee8e6bc07dbcebef938dc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 22 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-mapping-app-2600x1000.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Previously, we walked through creating a map that shows an interactive look at Coronavirus (COVID-19) cases per country. How can we extend this with some case statistics to show recent data about the impacts on our world?</p>
<p><em>Author's note: Similar to before, this dashboard is meant to be a demo and proof of concept for using real world data to build a dashboard. While this data should be accurate per the NovelCOVID API, I would recommend using tools like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a> for complete and accurate analysis. Stay home and be safe! ❤️</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</a></li>
<li><a class="post-section-overview" href="#heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</a></li>
<li><a class="post-section-overview" href="#heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</a></li>
<li><a class="post-section-overview" href="#heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</a></li>
<li><a class="post-section-overview" href="#heading-what-can-i-do-next">What can I do next?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9bfxeod27fU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We're going to be extending our <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">original map demo</a> with some basic statistics that we can retrieve from the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. To get an idea, here's <a target="_blank" href="https://coronavirus-map-dashboard.netlify.app/">my demo</a> I'm basing this off of.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-covid-19-dashboard-map-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map demo with dashboard statistics</em></p>
<p>While you're not required to have completed <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">Part 1</a> to apply these concepts, it definitely helps, and it lets you set up a map for your dashboard. If you'd like to start there, which I recommend, check out <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App with Gatsby and Leaflet</a> first.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven't played with maps before, don't be discouraged! It's not as bad as you probably think. If you'd rather start with mapping basics, you can  <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a>  first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>For this walkthrough, you pretty much need a React app in some form. I'll be working with the dashboard we previously built in my last walkthrough that includes a <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet/">map of the cases of the Coronavirus (COVID-19) per country</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-tutorial-country-markers.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) map dashboard</em></p>
<p>I recommend starting with the previous tutorial, but if you want to skip the map and start fresh, the easiest way would probably be to use <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a>, <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a>, or <a target="_blank" href="https://nextjs.org/">Next.js</a>.</p>
<h2 id="heading-step-1-update-how-we-fetch-our-data-and-fetch-the-statistics">Step 1: Update how we fetch our data and fetch the statistics</h2>
<p>To get started with our statistics dashboard, we're going to do a little prep work by changing how we're fetching the data. The goal here, is we're going to wrap our request logic in a reusable way so that we can use it for both our countries data and our new statistics data.</p>
<h3 id="heading-creating-a-new-react-hook-to-fetch-data">Creating a new React hook to fetch data</h3>
<p>Diving in, the first we'll do is create a new <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html">React hook</a> that will serve as how we fetch the data. To get started, create a new file in your hooks directory called <code>useTracker.js</code>  and add a line inside of <code>hooks/index.js</code> to export it:</p>
<pre><code class="lang-js"><span class="hljs-comment">// New file src/hooks/useTracker.js</span>
<span class="hljs-comment">// This will be empty for now</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Inside hooks/index.js</span>
<span class="hljs-keyword">export</span> { <span class="hljs-keyword">default</span> <span class="hljs-keyword">as</span> useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'./useTracker'</span>;
</code></pre>
<p>Inside of our <code>useTracker.js</code> file, we're going to set up our request logic. This is a long file, so make sure you copy and paste the entire thing before we walk through what it does:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> API_HOST = <span class="hljs-string">'https://corona.lmao.ninja/v2'</span>;

<span class="hljs-keyword">const</span> ENDPOINTS = [
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'all'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/all'</span>,
    <span class="hljs-attr">isDefault</span>: <span class="hljs-literal">true</span>
  },
  {
    <span class="hljs-attr">id</span>: <span class="hljs-string">'countries'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/countries'</span>
  }
]

<span class="hljs-keyword">const</span> defaultState = {
  <span class="hljs-attr">data</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>
}

<span class="hljs-keyword">const</span> useTracker = <span class="hljs-function">(<span class="hljs-params">{ api = <span class="hljs-string">'all'</span> }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> [tracker = {}, updateTracker] = useState(defaultState)

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchTracker</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ id } = {}</span>) =&gt;</span> id === api);

    <span class="hljs-keyword">if</span> ( !route ) {
      route = ENDPOINTS.find(<span class="hljs-function">(<span class="hljs-params">{ isDefault } = {}</span>) =&gt;</span> !!isDefault);
    }

    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'loading'</span>
        }
      });
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${API_HOST}</span><span class="hljs-subst">${route.path}</span>`</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> {
          ...prev,
          <span class="hljs-attr">state</span>: <span class="hljs-string">'error'</span>,
          <span class="hljs-attr">error</span>: e
        }
      });
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data } = response;

    updateTracker(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> {
        ...prev,
        <span class="hljs-attr">state</span>: <span class="hljs-string">'ready'</span>,
        data
      }
    });

  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetchTracker()
  }, [api])

  <span class="hljs-keyword">return</span> {
    fetchTracker,
    ...tracker
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useTracker;
</code></pre>
<p>Starting from the top:</p>
<ul>
<li>We import our dependencies: we're going to use Reacts <code>useEffect</code>  and <code>useState</code> hooks to manage our requests</li>
<li>We define default constants: we have a base API endpoint for our data, a list of the available endpoints we'll use, and a state object that will store our data</li>
<li>We define our <code>useTracker</code> hook:  our hook includes one argument <code>api</code>  that will allow us to specify which endpoint we'll use to make our request</li>
<li>We set up a state instance: we'll want to keep track of our fetched data, so we create a <code>tracker</code> state instance that we'll be able to update</li>
<li>We created an asynchronous <code>fetchTracker</code> function: we'll use this to make our actual request</li>
<li>Inside our function: we first find the API route and create our URL, update our state instance to a "loading" state, try to make our request, catch any errors if there are any, and finally if the request is successful, we update our state with that data</li>
<li>We trigger our function: using a <code>useEffect</code> hook, we trigger our <code>fetchTracker</code> function to make the request. We only have one dependency of <code>api</code>. This means the function will only fire the first time and any time the <code>api</code> value we pass in changes. We won't be changing that value, but it may be helpful in other instances if you're dynamically changing the API used</li>
<li>We return our tracker: the returned object includes both our <code>tracker</code> data as well as our <code>fetchTracker</code> function that we could use to refetch the data if we'd like</li>
</ul>
<p>And with all of that, we have a brand new hook that will fetch data from the NovelCOVID API.</p>
<h3 id="heading-using-our-new-tracker-hook">Using our new tracker hook</h3>
<p>To make use of this hook, let's jump over to <code>src/pages/index.js</code>, remove our <code>axios</code> import if it's there, and instead import our hook:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useTracker } <span class="hljs-keyword">from</span> <span class="hljs-string">'hooks'</span>;
</code></pre>
<p>With our hook, let's replace our original country data request.  First, add the following to the top of the <code>IndexPage</code> component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: countries = [] } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'countries'</span>
});

<span class="hljs-keyword">const</span> hasCountries = <span class="hljs-built_in">Array</span>.isArray(countries) &amp;&amp; countries.length &gt; <span class="hljs-number">0</span>;
</code></pre>
<p>This will let us fetch our country data and let us know if we have any results. Next, let's replace our original request.</p>
<p>Inside of our <code>mapEffect</code> function, let's remove the <code>axios</code> request in addition to the response, the destructured data object, and the <code>hasData</code> constant.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/code-diff-map-effect-countries-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Code diff showing update to map effect</em></p>
<p>Then, replace <code>hasData</code> with <code>hasCountries</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> ( !hasCountries ) <span class="hljs-keyword">return</span>;
</code></pre>
<p>And replace <code>data</code> with <code>countries</code> in the <code>geoJson</code> object where we map our features:</p>
<pre><code class="lang-js">features: countries.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
</code></pre>
<p>At this point, if you hit save and refresh, you shouldn't notice any difference to what you previously had.</p>
<h3 id="heading-add-a-request-for-our-stats">Add a request for our stats</h3>
<p>Now that we are using our <code>useTracker</code> hook to fetch our country data, let's also use that to fetch our stats.</p>
<p>Right next to where we set up our <code>useTracker</code> hook before, let's add another request:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: stats = {} } = useTracker({
  <span class="hljs-attr">api</span>: <span class="hljs-string">'all'</span>
});
</code></pre>
<p>And if we add a <code>console.log</code> statement under to see what's inside <code>stats</code>:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'stats'</span>, stats);
</code></pre>
<p>We should see our <code>stats</code> data object logged out!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/console-log-coronavirus-stats-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Using console.log to show Coronavirus (COVID-19) statistics</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/fe9d85e57f7474a86d38213676bf62df4b6168a4">Follow along with the commit!</a></p>
<h2 id="heading-step-2-adding-statistics-to-our-dashboard">Step 2: Adding statistics to our dashboard</h2>
<p>Now that we have our data available to use, let's use it!</p>
<p>To get started adding our statistics to the dashboard, let's create a data structure that will allow us to easily configure the data we want to use.</p>
<p>To do this, let's first create a new array called <code>dashboardStats</code> below <code>hasCountries</code> at the top of the page component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [];
</code></pre>
<p>Inside this array, let's add some new objects that specify our data that we're pulling from the <code>stats</code> object we requested. To start, let's try to add:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> dashboardStats = [
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Cases'</span>,
      <span class="hljs-attr">value</span>: stats?.cases
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.casesPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Deaths'</span>,
      <span class="hljs-attr">value</span>: stats?.deaths
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.deathsPerOneMillion
    }
  },
  {
    <span class="hljs-attr">primary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Total Tests'</span>,
      <span class="hljs-attr">value</span>: stats?.tests
    },
    <span class="hljs-attr">secondary</span>: {
      <span class="hljs-attr">label</span>: <span class="hljs-string">'Per 1 Million'</span>,
      <span class="hljs-attr">value</span>: stats?.testsPerOneMillion
    }
  }
]
</code></pre>
<p>The reason we're splitting this up into <code>primary</code> and <code>secondary</code> keys, is we're going to use that to differentiate between logically similar stats that we want to style a little bit differently.</p>
<p>_Note: if you're not familiar with the <code>?.</code> syntax, it's called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining">Optional Chaining</a>. This allows us to chain our properties without worrying about if the objects exist. If <code>stats</code> is undefined, it will simply return undefined instead of throwing an error._</p>
<p>With our stats data, let's add the tracker to our map. Let's remove our current <code>&lt;Map&gt;</code> component and include it nested inside our tracker div in the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Map</span> {<span class="hljs-attr">...mapSettings</span>} /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stats"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      { dashboardStats.map(({ primary = {}, secondary = {} }, i) =&gt; {
        return (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">Stat-</span>${<span class="hljs-attr">i</span>}`} <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat"</span>&gt;</span>
            { primary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-primary"</span>&gt;</span>
                { primary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ primary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            )}
            { secondary.value &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"tracker-stat-secondary"</span>&gt;</span>
                { secondary.value }
                <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{ secondary.label }<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            )}
          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        );
      })}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This code should be immediately following the <code>&lt;Helmet&gt;</code> component if you're following along.</p>
<p>To explain what we're doing:</p>
<ul>
<li>We're creating a "tracker" div that will organize our stats</li>
<li>We move our <code>&lt;Map</code> component inside of this tracker</li>
<li>We create a separate section called "tracker-stats"</li>
<li>Inside of this, we create an unordered list (<code>ul</code>)</li>
<li>Inside of our list, we loop through all of our stats inside <code>dashboardStats</code></li>
<li>For each stat, we create a new list element (<code>li</code>) and include 2 optional paragraphs that includes our primary stat data and our secondary stat data</li>
</ul>
<p>Once we reload our page, we should now see a few stats:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-stats-to-page.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding the first statistics to the page</em></p>
<p>Now that we have our stats on our page, let's make them look like they're in a dashboard.</p>
<p>Let's create a new file called <code>_tracker.scss</code> inside of our <code>src/assets/stylesheets/components</code> directory. Once that file is created, additionally add it to the <code>src/assets/stylesheets/components/__components.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@import</span> <span class="hljs-string">"tracker"</span>;
</code></pre>
<p>With our new component style file ready to go, let's add some styles into <code>_tracker.scss</code>:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-stats</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-top</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: grid;
    grid-template-<span class="hljs-attribute">columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat</span> {

  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2em</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">border-right</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);
  <span class="hljs-attribute">border-bottom</span>: solid <span class="hljs-number">1px</span> darken(<span class="hljs-variable">$blue-grey-900</span>, <span class="hljs-number">5</span>);

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-primary</span> {

  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  }

}

<span class="hljs-selector-class">.tracker-stat-secondary</span> {

  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">5em</span>;
  <span class="hljs-attribute">margin</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">strong</span> {
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">margin-left</span>: .<span class="hljs-number">4em</span>;
  }

}
</code></pre>
<p>Above – we're adding colors and organizational effects, such as using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout">CSS Grid</a>, to allow our data to be organized in an easy to read way and to look good! We're also making use of some pre-existing colors variables that are used within the project to keep the color use consistent.</p>
<p>Once you save those styles and reload the page, it should look much better:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/adding-coronavirus-case-statistics-to-map-dashboard.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding case statistics to the dashboard</em></p>
<p>From here, feel free to add more stats or adjust them to your liking. In the demo I created, I added the stats for active cases, critical cases, and recovered cases. If you'd like to do the same, you can <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">check out the commit</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/eb8a28c9e46dc2327ada0df21b250422e55d304c">Follow along with the commit!</a></p>
<h2 id="heading-step-3-make-the-data-human-friendly">Step 3: Make the data human friendly</h2>
<p>Now the rest of this walkthrough could be considered optional, but ultimately we want people to be able to read these statistics, right? So let's make the numbers a little more easy to read.</p>
<p>First, let's open our <code>src/lib/util.js</code> file and add this function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * commafy
 * <span class="hljs-doctag">@description </span>Applies appropriate commas to large numbers
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commafy</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">let</span> numberString = <span class="hljs-string">`<span class="hljs-subst">${value}</span>`</span>;

  numberString = numberString.split(<span class="hljs-string">''</span>);

  numberString.reverse();

  numberString = numberString.reduce(<span class="hljs-function">(<span class="hljs-params">prev, current, index</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> shouldComma = (index + <span class="hljs-number">1</span>) % <span class="hljs-number">3</span> === <span class="hljs-number">0</span> &amp;&amp; index + <span class="hljs-number">1</span> &lt; numberString.length;
    <span class="hljs-keyword">let</span> updatedValue = <span class="hljs-string">`<span class="hljs-subst">${prev}</span><span class="hljs-subst">${current}</span>`</span>;
    <span class="hljs-keyword">if</span> ( shouldComma ) {
      updatedValue = <span class="hljs-string">`<span class="hljs-subst">${updatedValue}</span>,`</span>;
    }
    <span class="hljs-keyword">return</span> updatedValue;
  }, <span class="hljs-string">''</span>);

  numberString = numberString.split(<span class="hljs-string">''</span>);
  numberString.reverse()
  numberString = numberString.join(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">return</span> numberString;
}
</code></pre>
<p>This function will take a number and turn it into a string with commas. To walk through what it does:</p>
<ul>
<li>Takes in a value as an argument. For our use, this value will most likely be a number.</li>
<li>It converts the value into a string. We'll use this to work with adding commas to our number.</li>
<li>We split that string into an array and reverse it. We want to reverse it because it makes it easier to add our commas depending on the index.</li>
<li>We use the javascript <code>reduce</code> function to recreate our number-string. After every 3 numbers, we want to add a comma.</li>
<li>Once we have our new value with the commas, we want to re-reverse it. So we split it again, reverse the array of characters, and re-join it, which is what we return</li>
</ul>
<p>And now that we have our <code>commafy</code> function, let's use it. Back inside <code>src/pages/index.js</code>, let's import our function at the top of the page:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then, in our <code>dashboardStats</code> array, let's replace every number value with a ternary expression and function that will convert our number if it's available:</p>
<pre><code class="lang-js">value: stats ? commafy(stats?.cases) : <span class="hljs-string">'-'</span>
</code></pre>
<p>This line checks to see if <code>stats</code> exists. If it does, we <code>commafy</code> the <code>cases</code> value. If it doesn't exist, we return a <code>-</code> to show it's unavailable.</p>
<p>Once we repeat that process for all of our numbers, we can save, reload the page, and see our human friendly numbers!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-stats-with-readable-stats.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the statistics to be human readable</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/90f266c17815239d9d3356d9b9d660915fdc26c2">Follow along with the commit!</a></p>
<h2 id="heading-step-4-add-the-last-updated-date">Step 4: Add the Last Updated date</h2>
<p>Finally, we want to make sure people are staying informed and understand the last time this data was updated. Luckily, our API provides a Last Updated date for us, so let's use it!</p>
<p>At the bottom of our "tracker" <code>div</code> under <code>tracker-stats</code>, let's add the following:</p>
<pre><code class="lang-jsx">&lt;div className=<span class="hljs-string">"tracker-last-updated"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    Last Updated: { stats?.updated }
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This creates a new section where we simply include the <code>updated</code> property from our stats. And if we save and reload the page, we can see the last updated date!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Adding last updated to the dashboard</em></p>
<p>But how could we even understand what that number is, unless you're the computer crawling this blog post? So let's change it to a human readable format like we did with our numbers.</p>
<p>Inside of our <code>src/lib/util.js</code> file, let's add another function:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * friendlyDate
 * <span class="hljs-doctag">@description </span>Takes in a date value and returns a friendly version
 */</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">friendlyDate</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(value);
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(<span class="hljs-string">'en'</span>, {
    <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">month</span>: <span class="hljs-string">'short'</span>,
    <span class="hljs-attr">day</span>: <span class="hljs-string">'2-digit'</span>,
    <span class="hljs-attr">hour</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">minute</span>: <span class="hljs-string">'numeric'</span>
  }).format(date);
}
</code></pre>
<p>This function creates a new <code>Date</code> object, then uses the javascript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">International DateTimeFormat API</a> to convert it into a friendly readable format!</p>
<p>Once that's saved, let's import it next to our <code>commafy</code> function at the top of <code>src/pages/index.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { commafy, friendlyDate } <span class="hljs-keyword">from</span> <span class="hljs-string">'lib/util'</span>;
</code></pre>
<p>Then we can update our code similar to how we updated our numbers:</p>
<pre><code class="lang-jsx">Last Updated: { stats ? friendlyDate(stats?.updated) : <span class="hljs-string">'-'</span> }
</code></pre>
<p>And if we save and reload, we see it in a human readable way!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronvirus-dashboard-last-updated-formatted-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Formatting the last updated date</em></p>
<p>Finally for our "last updated" should look like it fits in with the rest of the dashboard, so let's add a few more styles. Inside of our <code>_tracker.scss</code> file we were working with earlier:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.tracker-last-updated</span> {

  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">padding</span>: .<span class="hljs-number">8em</span> <span class="hljs-number">0</span>;

  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-300</span>;
    <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">8em</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>And once we hit save and refresh the browser, we have our dashboard statistics with the last updated time! ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-dashboard-formatted-styled.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Final dashboard with formatted lasted updated date</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/408286aecb32223c8782eb1539f5563135c75dfb">Follow along with the commit!</a></p>
<h2 id="heading-what-can-i-do-next">What can I do next?</h2>
<h3 id="heading-make-the-marker-tooltip-data-human-friendly">Make the marker tooltip data human friendly</h3>
<p>Now that we have our handy <code>commafy</code> and <code>friendlyDate</code> functions, we can reuse those functions to clean up the data in our country marker popups!</p>
<h3 id="heading-use-the-fetchtracker-function-to-poll-for-updates">Use the fetchTracker function to poll for updates</h3>
<p>Inside of the <code>useTracker</code> hook we created, we exported a function called <code>fetchTracker</code>. This allows us to force a request to the API to fetch new data. To make sure our map stays current even when somebody doesn't refresh the page, we can create a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">timer</a> in javascript to regularly invoke that function to update our dashboard data.</p>
<h3 id="heading-clear-the-map-layers-before-re-adding-the-new-ones">Clear the map layers before re-adding the new ones</h3>
<p>One thing we're currently not doing is cleaning up old layers before adding a new one. The way the map is set up, it just keeps layering them on top. What we can do is before we add all of our new layers, we can clear out the old ones. <a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/cad3b5a6e31a6ae090549c12e40a08fee4db4aa5">Check out this commit</a> to get started!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a> (Part 1 of this post)</li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Lessons We Can Learn from Git Revert in Our Fight with COVID-19 ]]>
                </title>
                <description>
                    <![CDATA[ By Syk Houdeib In this article, I'll discuss how a small tech team found itself in the middle of a national emergency in Spain. And what their use of git revert can teach us about dealing with COVID-19 in our personal lives. Intro It was late in the ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-we-can-learn-from-git-revert-in-our-fight-against-covid19/</link>
                <guid isPermaLink="false">66d461553bc3ab877dae2245</guid>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Life Lesson ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Spain ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 08 Apr 2020 07:17:58 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9bbb740569d1a4ca2d97.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Syk Houdeib</p>
<p>In this article, I'll discuss how a small tech team found itself in the middle of a national emergency in Spain. And what their use of git revert can teach us about dealing with COVID-19 in our personal lives.</p>
<h2 id="heading-intro">Intro</h2>
<p>It was late in the afternoon of Wednesday 11th of March 2020. There were a few of us left in the office in the centre of Madrid as we got notified to take our laptops with us home today. Starting the day after we were to work remotely until further notice. </p>
<p>Two days earlier the government had closed all schools and universities because of the Coronavirus emergency. There was a lot of uncertainty, and things were changing at a fast pace. None of us really knew what was going to happen next.</p>
<p>The mood became sombre as we packed our stuff. We started making grim predictions about how long it would be before we came back. Little did we know that we were a few days away from a declaration of a nation-wide state of emergency. And that at the time of writing we are still weeks away from going back to that office in the centre of Madrid.</p>
<p>I want to share with you this article in two sections. The first a quick tour of how my team found itself at the centre of this national emergency. To give you an idea about how we reacted. </p>
<p>But in essence, I'm sharing this with you because I found a valuable lesson in that response for my personal life. And I'm hoping you too might find some value in it as we all deal with this worsening COVID-19 crisis and the changing world around us.</p>
<p>At the heart of all of this is a little checkbox titled "Revert".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-176.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@martinsanchez?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Martin Sanchez / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h2 id="heading-in-the-eye-of-the-hurricane">In the eye of the hurricane</h2>
<p>I'm a front-end developer at Lola Market. It's a Spanish startup based in Madrid. Our business is offering a platform for online grocery shopping. Users can do their grocery shopping online from a wide selection of markets and supermarkets. Their orders then get sent to shoppers who can deliver it to their doorstep within an hour.</p>
<p>This has suddenly become an essential service right now.  If you are reading this and you are one of the millions that are currently on lockdown because of the coronavirus I don't need to explain to you why. But for posterity, I will. Believe it or not, this will all soon pass, and there will come a moment when it's not as evident as it is now.</p>
<p>Once the Spanish government declared the state of emergency the entire country went into lockdown. People were no longer allowed to leave their homes except for essentials. </p>
<p>Certain groups were in total quarantine which doesn't allow them to leave the house at all. This includes people who have any COVID-19 symptoms. Those who had contact with anyone who tested positive. Or people in high-risk groups.</p>
<p>In light of all this, getting shopping ordered online and delivered to the home stopped being a convenience. It was now a necessity for many people.</p>
<p>Lola Market, on the eve of the declaration of the state of emergency, was still a small startup. I have been there for nearly two years during which time we have seen steady and impressive growth. </p>
<p>We had changed offices a year ago and almost doubled in number. But we were still barely 40 people in total. The tech team is made up of 11 people, 8 of whom are developers. Our customer care team is even smaller.</p>
<p>The CEO only a few weeks earlier was talking about getting ready for the moment of exponential growth that we were working towards. But we had no idea that a worldwide pandemic was going to catapult us there so soon at this vertiginous speed. </p>
<h2 id="heading-the-flood">The flood</h2>
<p>Once the state of emergency was declared, we instantly started breaking all sorts of records. We watched as the number of orders exploded.</p>
<p>At first, all went well. But the numbers kept growing and growing. By the second week of the lockdown, the demand had exceeded everything that could be handled. </p>
<p>Customer care department was overwhelmed with thousands of emails and calls. Operations were struggling as supermarkets suffered serious shortages, long lines, early closures, and a lot of restrictions. As well as not having enough shoppers to cover the demand.</p>
<p>And our tech infrastructure started to suffer under a pressure that wasn't just coming from a huge increase of traffic. But also because the tools we had were being used in an atypical manner that didn't follow what we were used to with our usual user before the emergency. The entire country was stressed and under pressure. Everyone needed to cover their essentials.</p>
<p>One has to count their blessings though. Personally I was grateful to be in this situation. All around me people were losing their jobs in a blink of an eye. </p>
<p>And it wasn't just that we had a job to go to, it was that our job gave us the sensation that we are contributing to relief in a state of emergency. Even if it was in the smallest way possible. It gave us a purpose and made what we are doing worthwhile. And that's more than one could ask for in a dire situation like this.</p>
<h2 id="heading-the-shift">The shift</h2>
<p>Pretty early on, we had a meeting and our CTO told us how we needed to shift our priorities and respond to the sudden change.</p>
<p>We were in the middle of an important sprint finishing off the last projects of the quarter. But most of those projects were no longer a priority. The sprint needed to be suspended as we started dealing with the more urgent matters coming up.</p>
<p>In the first week, we needed to figure out ways to help out the rest of the team in other departments to deal with the great volume they were facing.</p>
<p>Even something as simple as moving a menu in an internal tool to be easily accessible could save hours of work when you are dealing with so much sudden demand. But by the second week, we had even more serious issues to deal with to be able to absorb and control the surge in demand on our infrastructure.</p>
<h2 id="heading-the-changes">The changes</h2>
<p>Over these last few weeks, we've had to implement a lot of changes on the fly to deal with this ever-changing situation. Some of the things entrusted to the tech team to solve included: </p>
<ul>
<li>Showing dynamic and clearer information to our users about the situation and about the state of their orders.</li>
<li>Simplifying and automating parts of the process of on-boarding new shoppers to speed up the process and help meet the demand.</li>
<li>Trying to show more realistic availability of delivery time slots.</li>
<li>Big improvements and optimisations of infrastructure, performance, customer care tools, operations tools, and the shopper app.</li>
<li>Automation of many internal tasks, especially those that have become repetitive.</li>
<li>Making the API load lighter.</li>
</ul>
<p><em>Disclaimer: This is a personal article and not an official statement from the company. At the time of writing we are still in the thick of it. Some changes are already deployed. Others we are still implementing. And the situation is constantly changing.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-177.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@glenncarstenspeters?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Glenn Carstens-Peters / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h2 id="heading-the-emergency-list">The emergency list</h2>
<p>You can imagine that working in such circumstances is a challenge for any team, let alone a team of such a small size. It has been stressful and exhilarating in equal parts. </p>
<p>But I'm lucky to work with such a positive team. Especially the 4-person back end squad who dealt stoically with moments of complete meltdown and figured out solutions at an astonishing speed.</p>
<p>This brings me to the element that connects the two sections of this article: the emergency list.</p>
<p>To deal with all these tasks, and the constant shifts, we created an emergency list. It's a simple list of tasks in a Notion table. As the situation evolved the list kept on growing and the tasks kept altering in priority.</p>
<p>The most important part of that list for our story here is the column titled "Revert". The column contains a checkbox next to each task. It is this little checkbox that resonated with me and gave me an idea about how I should be dealing with this crisis on a personal level too. </p>
<h2 id="heading-revert">Revert</h2>
<p>We use the "Revert" checkbox to indicate clearly if this is a task that should be reverted once this is all over or not.</p>
<p>If the revert checkbox is checked it means it's a task that we are doing now to solve a specific problem that, once the crisis is over and we're back to normal, we'll need to revert. </p>
<p>This is something that only has value in this emergency and its context. It serves a purpose now, but will no longer be needed later. Many of these changes will, in fact, be downright harmful once the emergency passes.</p>
<p>If this checkbox is unchecked, it means that whatever we are changing is staying after the crisis is over. It's something that we knew all along we needed to do but hadn't come around doing it. But because of this situation has become a priority. </p>
<p>Or it's something we didn't see and it's become obvious now. These are things to help us scale better, and improve our service in general. They are things that are settling a technical debt that has become vital to pay. They are improvements to our codebase, our infrastructure, or our processes that are beneficial in the long run and not just for now.</p>
<p>What we are doing is we are thinking of the future, of what happens once all this passes. Because it will. And life will go back to its natural course. We will be changed, and the world around us too. But life will carry on.</p>
<p>A pandemic that most of us weren't prepared to face created havoc in our lives and our businesses. But we cannot permit this crisis to create total chaos in our lives afterwards too. We should be prepared for the time it all passes.</p>
<h2 id="heading-applying-the-revert-to-our-personal-lives">Applying the revert to our personal lives</h2>
<p>So how does any of this relate to our lives as we deal with this COVID-19 world we're living in and its aftermath?</p>
<p>Simply put, we all need a revert checkbox. We need it next to the many changes we are applying to our lives. Changes we are applying to deal with the virus, with our jobs, with our families and the world at large as we navigate this unprecedented situation.</p>
<p>For me, I'm keeping a similar kind of list for my personal life. We can all have a list like this one. Document it the way you know best. Whether it's a written list, a mental list or any other type of documenting you usually use. It doesn't matter. What matters is to have that "Revert" checkbox.</p>
<p>As we all grapple with this extraordinary situation and all the fear, hardship, uncertainty, and even tragedy it brings with it. We all have a list of things we are doing born out of this emergency.</p>
<p>We need to keep clear what needs to be reverted later and what needs to stay. We are very quick to form habits. Many of us have already spent a month indoors. Many more will follow suit soon as this thing keeps spreading. We can't even tell how long we are going to be in this situation.</p>
<p>So we need to keep that revert checkbox as prominent as possible.</p>
<p>We need to examine the list of changes that we are applying to our new reality.</p>
<p>If it's something that is improving us and our lives, keep that checkbox clear. Maybe you realised you should call your Mum more often. Or nurture your old friendships. Or spend more time with your kids. Or never take for granted the hugs you can give to your grandparents. </p>
<p>Maybe it's something as simple as being thankful that you can have a beer with your friends. Or listening to a busker on a busy street corner on your way back from work.</p>
<p>Mark those as habits to keep. Things to continue working on and improving after this passes.</p>
<p>But for anything else, all those things that will not be helpful after. We need to check the "Revert" box.</p>
<p>All the things that are helping us survive an ordeal, helping us cope with this, deal with it. All the fears that are important to keeping us on our toes and staying safe. All the extra precautions. The distancing. The little things we are allowing ourselves. The indulgences. The excesses. All those things that will quickly become harmful to us in a life after COVID-19.</p>
<p>For those make sure you check the "Revert" checkbox with a big fat green marker. ✅</p>
<p>Once this is over, it'll be time to revert. Time to undo all that and move forward.</p>
<h2 id="heading-outro">Outro</h2>
<p>Thank you for reading. I hope you and your loved ones stay safe and that life returns to normal for all of us very soon.  </p>
<p>And good luck with your revert checkboxes.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to create a Coronavirus (COVID-19) Dashboard & Map App in React with Gatsby and Leaflet ]]>
                </title>
                <description>
                    <![CDATA[ The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world? Update: The original NovelCOVID API v1 endpoint has been de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/</link>
                <guid isPermaLink="false">66bee92588139a9746c0c5cc</guid>
                
                    <category>
                        <![CDATA[ coronavirus ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Covid-19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analytics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Tue, 31 Mar 2020 15:16:16 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-mapping-app.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Coronavirus (COVID-19) pandemic has swiftly changed how all of us interact day to day. How can we use available APIs to build a mapping app that shows the impact it has had on the world?</p>
<p><strong>Update:</strong> The original NovelCOVID API v1 endpoint has been deprecated. Please update and use the following instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a></p>
<p><em>Author’s Note: This is meant to be a demo and proof of concept for putting together an impactful mapping application using real life data. For complete and accurate analysis, please make sure to use tools like <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University dashboard</a>. Stay home and be safe! ❤️</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-do-we-need-before-we-get-started">What do we need before we get started?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</a></li>
<li><a class="post-section-overview" href="#heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</a></li>
<li><a class="post-section-overview" href="#heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</a></li>
<li><a class="post-section-overview" href="#heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</a></li>
<li><a class="post-section-overview" href="#heading-what-else-can-we-do">What else can we do?</a></li>
<li><a class="post-section-overview" href="#heading-be-safe-and-stay-informed">Be safe and stay informed</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/GryBIsfBfro" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’ll be putting together a mapping application that uses an API containing recent Coronavirus statistics and maps out the locations and impact each country is facing.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus map dashboard demo</em></p>
<p>On the map, we’ll show a marker for each country with the number of confirmed cases. On top of that, we’ll include a little popup tooltip that shows more in depth information.</p>
<p>The map we’ll build will mostly look like the above, but will look a little simpler. We’ll utilize the OpenStreetMap public tileserver instead of using a custom <a target="_blank" href="https://www.mapbox.com/">Mapbox</a></p>
<p>To get started, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created to make the initial setup a little smoother. With our app bootstrapped, we’ll fetch our data and add markers to the map with our data.</p>
<h2 id="heading-woah-a-mapping-app">Woah, a mapping app?</h2>
<p>Yup. If you haven’t played with maps before, don’t be discouraged! It's not as bad as you probably think. If you’d rather start with mapping basics, you can <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">read more about how mapping works</a> first.</p>
<h2 id="heading-what-do-we-need-before-we-get-started">What do we need before we get started?</h2>
<p>If you followed along with my previous tutorials for <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">building a Santa Tracker</a> or <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">creating a Summer Road Trip map</a>, you can follow the same steps to get started. If not, we’ll want to make sure we have the following set up:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">node</a> or <a target="_blank" href="https://yarnpkg.com/en/">yarn</a> - I'll be using yarn, but you can substitute with npm where appropriate</li>
<li><a target="_blank" href="https://www.gatsbyjs.org/docs/gatsby-cli/">Gatsby’s CLI</a> - <code>yarn global add gatsby-cli</code></li>
</ul>
<p>If you’re not sure about one of the above, you can try checking out the beginning <a target="_blank" href="https://www.freecodecamp.org/news/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">my previous tutorial</a>.</p>
<p>We’ll also want to set up a foundation for our map. We can do this by utilizing the Leaflet Gatsby Starter I put together that provides us a basic setup with <a target="_blank" href="https://leafletjs.com/">Leaflet</a> and <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a>.</p>
<pre><code class="lang-shell">gatsby new my-coronavirus-map https://github.com/colbyfayock/gatsby-starter-leaflet
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-creating-new-coronavirus-map-from-gatsby-starter.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Leaflet Gatsby app in the terminal</em></p>
<p>After that’s finished running, you can navigate to the newly created project directory and start your local development server:</p>
<pre><code class="lang-shell">cd my-coronavirus-map
yarn develop
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/terminal-starting-gatsby-development-server-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting your Gatsby app in the terminal</em></p>
<p>If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/gatsby-starter-leaflet-in-browser-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commits/master">Follow along with the commit!</a></p>
<h2 id="heading-step-1-cleaning-up-some-unneeded-code">Step 1: Cleaning up some unneeded code</h2>
<p>The Gatsby Starter we're using to spin up this app comes with some demo code that we don’t need here. We’ll want to make all of the changes below in the file <code>src/pages/index.js</code>, which is the homepage of our app.</p>
<p>First, let’s remove everything from the <code>mapEffect</code> function. This function is used to run code that fires when the map renders.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// In src/pages/index.js</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement } = {}</span>) </span>{
  <span class="hljs-comment">// Get rid of everything in here</span>
}
</code></pre>
<p>We’ll also change the variable name of our <code>leafletElement</code> simply for being able to more easily understand the code as we write it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
}
</code></pre>
<p>Next, we don’t want a marker this time, so let’s remove the <code>&lt;Marker</code> component from our <code>&lt;Map</code> component:</p>
<pre><code class="lang-react">&lt;Map {...mapSettings} /&gt;
</code></pre>
<p>Now that we have those pieces cleared out, we can remove all of the following imports and variables from the top of our file:</p>
<ul>
<li>useRef</li>
<li>Marker</li>
<li>promiseToFlyTo</li>
<li>getCurrentLocation</li>
<li>gatsby_astronaut</li>
<li>timeToZoom</li>
<li>timeToOpenPopupAfterZoom</li>
<li>timeToUpdatePopupAfterZoom</li>
<li>ZOOM</li>
<li>popupContentHello</li>
<li>popupContentGatsby</li>
<li>markerRef</li>
</ul>
<p>After, our map should still work, but not do anything.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/new-empty-mapping-app-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New mapping app with nothing going on</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/a3e9cff3949bb7ebb7cc89166c875e97b6dcb5a8">Follow along with the commit!</a></p>
<h2 id="heading-step-2-fetching-the-coronavirus-data">Step 2: Fetching the Coronavirus data</h2>
<p>For our app, we’re going to use the <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a>. Particularly, we’re going to use the <a target="_blank" href="https://corona.lmao.ninja/countries">countries endpoint</a> to fetch the list of our countries and the stats associated with them.</p>
<p>For making requests, I personally like to use <a target="_blank" href="https://github.com/axios/axios">axios</a> as it has a nice to use API. If you want to use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch</a> or your own favorite request library, substitute that in for this step.</p>
<p>We’ll start by installing axios:</p>
<pre><code class="lang-shell">yarn add axios
</code></pre>
<p>Once that installs, remember to restart your server.</p>
<p>Import the axios package ta the top of our <code>pages/index.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
</code></pre>
<p>Next we’ll actually make our request. Inside our <code>mapEffect</code> function, let’s try to make a request to the API endpoint:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mapEffect</span>(<span class="hljs-params">{ leafletElement: map } = {}</span>) </span>{
    <span class="hljs-keyword">let</span> response;

    <span class="hljs-keyword">try</span> {
      response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'https://corona.lmao.ninja/v2/countries'</span>);
    } <span class="hljs-keyword">catch</span>(e) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Failed to fetch countries: <span class="hljs-subst">${e.message}</span>`</span>, e);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> { data = [] } = response;
}
</code></pre>
<p>In this snippet, we’re doing the following:</p>
<ul>
<li>Setting up a <code>response</code> variable that will allow us to store the response</li>
<li>Adding a <code>try/catch</code> block that will catch any API errors if the request fails</li>
<li>If the request is successful, we store the response in the <code>response</code> variable</li>
<li>If the request fails, we console log out the error and return out of the function so we don’t continue to run the code with a failed request</li>
<li>Once we have our response, we can destructure <code>data</code> from the response and set the default value to an empty array, as that will be the type of data we need</li>
</ul>
<p>After that’s set up, we can console log out the <code>data</code> object and we’ll see our data successfully fetched!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/coronavirus-location-data-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Logging the Coronavirus location data to the browser console</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/86bebfee4a34b9bad516879b228921cdaad55126">Follow along with the commit!</a></p>
<p><strong>Update:</strong> The previous commit includes a link to the original NovelCOVID v1 API endpoint which has now been deprecated. Please use this instead: <a target="_blank" href="https://corona.lmao.ninja/v2/countries">https://corona.lmao.ninja/v2/countries</a>.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/e8f63c7ca60ec358b2edc9bc3ed8935be85b5573">See updated commit</a>.</p>
<h2 id="heading-step-3-transform-the-coronavirus-data-into-a-geographic-data-format">Step 3: Transform the Coronavirus data into a geographic data format</h2>
<p>Now that we have our data, we can transform it into a geographic data format, particularly <a target="_blank" href="https://geojson.org/">GeoJSON</a>, that will allow us to interface with Leaflet.</p>
<p>Let’s start by adding this block of code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { data = [] } = response;
<span class="hljs-keyword">const</span> hasData = <span class="hljs-built_in">Array</span>.isArray(data) &amp;&amp; data.length &gt; <span class="hljs-number">0</span>;

<span class="hljs-keyword">if</span> ( !hasData ) <span class="hljs-keyword">return</span>;

<span class="hljs-keyword">const</span> geoJson = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'FeatureCollection'</span>,
  <span class="hljs-attr">features</span>: data.map(<span class="hljs-function">(<span class="hljs-params">country = {}</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { countryInfo = {} } = country;
    <span class="hljs-keyword">const</span> { lat, <span class="hljs-attr">long</span>: lng } = countryInfo;
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'Feature'</span>,
      <span class="hljs-attr">properties</span>: {
       ...country,
      },
      <span class="hljs-attr">geometry</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'Point'</span>,
        <span class="hljs-attr">coordinates</span>: [ lng, lat ]
      }
    }
  })
}
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new constant called <code>hasData</code> that checks if our <code>data</code> variable is an array and has data</li>
<li>If we don’t have data, we want to return out of the function, as we don’t want to try to add data we don’t have</li>
<li>We create a <code>geoJson</code> object that will be our GeoJSON document</li>
<li>Our document is of type <code>FeatureCollection</code> and as our <code>features</code> we loop through our dataset</li>
<li>For each country in our data, we obtain the <code>lat</code> and <code>lng</code> to create a point for our map</li>
<li>We additionally add our country data as properties so we can access it within our mapping APIs</li>
</ul>
<p>If you <code>console.log</code> this object our into your browser and copy the contents, you can paste this into geojson.io and see the location data show up correctly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/location-data-geojson-io.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Previewing Coronavirus location data on geojson.io</em></p>
<p>With this GeoJSON document, we'll now be able to add it to our map.</p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/f0da2d05cbc16783322684da7a3efaa61022f5b6">Follow along with the commit!</a></p>
<h2 id="heading-step-4-adding-the-coronavirus-data-to-the-map">Step 4: Adding the Coronavirus data to the map</h2>
<p>We have our GeoJSON document with our location data, so let’s add it to the map.</p>
<p>Let’s start with this code block. It's a long one, but we’ll break it down piece by piece:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> geoJsonLayers = <span class="hljs-keyword">new</span> L.GeoJSON(geoJson, {
  <span class="hljs-attr">pointToLayer</span>: <span class="hljs-function">(<span class="hljs-params">feature = {}, latlng</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { properties = {} } = feature;
    <span class="hljs-keyword">let</span> updatedFormatted;
    <span class="hljs-keyword">let</span> casesString;

    <span class="hljs-keyword">const</span> {
      country,
      updated,
      cases,
      deaths,
      recovered
    } = properties

    casesString = <span class="hljs-string">`<span class="hljs-subst">${cases}</span>`</span>;

    <span class="hljs-keyword">if</span> ( cases &gt; <span class="hljs-number">1000</span> ) {
      casesString = <span class="hljs-string">`<span class="hljs-subst">${casesString.slice(<span class="hljs-number">0</span>, <span class="hljs-number">-3</span>)}</span>k+`</span>
    }

    <span class="hljs-keyword">if</span> ( updated ) {
      updatedFormatted = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(updated).toLocaleString();
    }

    <span class="hljs-keyword">const</span> html = <span class="hljs-string">`
      &lt;span class="icon-marker"&gt;
        &lt;span class="icon-marker-tooltip"&gt;
          &lt;h2&gt;<span class="hljs-subst">${country}</span>&lt;/h2&gt;
          &lt;ul&gt;
            &lt;li&gt;&lt;strong&gt;Confirmed:&lt;/strong&gt; <span class="hljs-subst">${cases}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Deaths:&lt;/strong&gt; <span class="hljs-subst">${deaths}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Recovered:&lt;/strong&gt; <span class="hljs-subst">${recovered}</span>&lt;/li&gt;
            &lt;li&gt;&lt;strong&gt;Last Update:&lt;/strong&gt; <span class="hljs-subst">${updatedFormatted}</span>&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/span&gt;
        <span class="hljs-subst">${ casesString }</span>
      &lt;/span&gt;
    `</span>;

    <span class="hljs-keyword">return</span> L.marker( latlng, {
      <span class="hljs-attr">icon</span>: L.divIcon({
        <span class="hljs-attr">className</span>: <span class="hljs-string">'icon'</span>,
        html
      }),
      <span class="hljs-attr">riseOnHover</span>: <span class="hljs-literal">true</span>
    });
  }
});
</code></pre>
<p>So what are we doing here?</p>
<ul>
<li>We create a new instance of <code>L.GeoJSON</code> which will transform our GeoJSON document into something Leaflet will understand</li>
<li>Inside that instance, we define a custom <code>pointToLayer</code> function. This allows us to customize the map layer Leaflet creates for our map</li>
<li>In our function, we assign and create our datapoints that we want. Most of it is destructuring, but we format the cases count to show <code>1k+</code> instead of <code>1000</code> and a formatted date instead of the timestamp</li>
<li>We create an HTML string block which is used to define our map marker that will be added to the map. This also includes the HTML for the tooltip that will pop up when hovering over a marker</li>
<li>We return <code>L.marker</code> with our custom configuration that includes a class of <code>icon</code> for the container and our custom HTML.</li>
<li>Additionally, we add the <code>riseOnHover</code> property so when hoving over a marker, it surfaces itself above over the other markers on the map</li>
</ul>
<p>We also want to add a bit of CSS here so that we can make sure our markers show up in the map and are usable. Let’s add this snippet to our <code>assets/stylesheets/components/_map.scss</code> file:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.icon-marker</span> {

  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">3.6em</span>;
  <span class="hljs-attribute">font-size</span>: .<span class="hljs-number">7em</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$red-800</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:hover</span> {

    <span class="hljs-selector-class">.icon-marker-tooltip</span> {
      <span class="hljs-attribute">display</span>: block;
    }

  }

}

<span class="hljs-selector-class">.icon-marker-tooltip</span> {

  <span class="hljs-attribute">display</span>: none;
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">bottom</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">16em</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.4em</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
  <span class="hljs-attribute">border-radius</span>: .<span class="hljs-number">4em</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">5px</span> rgba(black, .<span class="hljs-number">9</span>);

  &amp;<span class="hljs-selector-pseudo">:before</span> {
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">bottom</span>: -.<span class="hljs-number">6em</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">1.4em</span>;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$blue-grey-900</span>;
    <span class="hljs-attribute">transform</span>: rotate(<span class="hljs-number">45deg</span>);
    <span class="hljs-attribute">margin-left</span>: -.<span class="hljs-number">7em</span>;
  }

  <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5em</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.2</span>;
    <span class="hljs-attribute">margin-bottom</span>: .<span class="hljs-number">1em</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-tag">h3</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2em</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">1em</span> <span class="hljs-number">0</span>;
    <span class="hljs-attribute">font-weight</span>: normal;
    <span class="hljs-attribute">color</span>: <span class="hljs-variable">$blue-grey-100</span>;
  }

  <span class="hljs-selector-tag">ul</span>,
  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">font-weight</span>: normal;
  }

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: .<span class="hljs-number">6em</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  }

}
</code></pre>
<p>What we’re doing:</p>
<ul>
<li>We create our round markers using the <code>.icon-marker</code> class and set up our <code>.icon-marker-tooltip</code> class to show up when hovered over</li>
<li>Our <code>.icon-marker-tooltip</code> class is hidden by default, as it’s our tooltip, but we position it absolutely to appear over top of our marker and formatted the way we want it</li>
</ul>
<p>And finally, once we have our <code>geoJsonLayers</code> created with our styling added, we can add it to the map!</p>
<pre><code>geoJsonLayers.addTo(map)
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data</em></p>
<p>Now you might be wondering why it doesn't appear to be centering properly. Go ahead and change the <code>LOCATION</code> variable at the top of the <code>index.js</code> file to:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> LOCATION = {
  <span class="hljs-attr">lat</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lng</span>: <span class="hljs-number">0</span>
};
</code></pre>
<p>Once that’s set, when the page reloads, the map should be centered in the middle of the world!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/map-with-coronavirus-location-data-centered-tooltip.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Map with Coronavirus location data centered with a tooltip</em></p>
<p><a target="_blank" href="https://github.com/colbyfayock/my-coronavirus-map/commit/49c78e4ef3e98c974fab7bca10b6f8f7578b42c2">Follow along with the commit!</a></p>
<h2 id="heading-yay-we-did-it">Yay, we did it! ?</h2>
<p>If you followed along, you now have created your own Coronavirus map dashboard that gives some quick stats about the cases around the world.</p>
<p>Take what you learned and run with it. You can apply this to any other type of data that you can imagine.</p>
<h2 id="heading-what-else-can-we-do">What else can we do?</h2>
<h3 id="heading-add-more-styles-and-a-custom-basemap">Add more styles and a custom basemap</h3>
<p>In my original demo, I set up a custom basemap using <a target="_blank" href="https://mapbox.com/">Mapbox</a> that allows me to have a dark background making the markers easier to see.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/mapbox-studio-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new basemap in Mapbox Studio</em></p>
<p>Mapbox is great and has a nice free tier if you’re interested in getting started.</p>
<p>Once you have a Mapbox account, you can even <a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">copy the style</a> I used and make it your own.</p>
<p><a target="_blank" href="https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0.html?fresh=true&amp;title=copy&amp;access_token=pk.eyJ1IjoiY29sYnlmYXlvY2siLCJhIjoiY2swODZzbXYxMGZzdzNjcXczczF6MnlvcCJ9.HCfgUYZUTP7uixjYF7tBSw">Basic Dark Mapbox Theme</a></p>
<p>To learn how to integrate it, you can try to check out the source code of <a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">my original demo</a>:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/coronavirus-map-dashboard">https://github.com/colbyfayock/coronavirus-map-dashboard</a></p>
<h3 id="heading-add-overview-dashboard-stats">Add overview dashboard stats</h3>
<p>Dashboards with maps like the <a target="_blank" href="https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6">Johns Hopkins University app</a> allows us to see more than a look on the map, but a glimpse at quick stats about the cases around the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/johns-hopkins-coronavirus-map-march-29.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Johns Hopkins University Coronavirus Map Dashboard - March 29, 2020</em></p>
<p>The <a target="_blank" href="https://github.com/NovelCOVID/API">NovelCOVID API</a> has more endpoints like <code>/all</code> that provide a few global stats.</p>
<h2 id="heading-be-safe-and-stay-informed">Be safe and stay informed</h2>
<p>I want to reiterate that you should make sure you're staying up to date using official sources for information, such as the Johns Hopkins University dashboard. Though the data should be reliable, it should also be considered a proof of concept for building a map and referencing, but shouldn't be considered for any kind of statistical analysis.</p>
<p>Please take care of yourself during these times. We're all in this together! ❤️</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/04/how-to-set-up-a-custom-mapbox-basemap-style-with-react-leaflet-and-leaflet-gatsby-starter/">How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
