├── .all-contributorsrc ├── .babelrc ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── _redirects ├── assets ├── images │ ├── add_to_hs │ │ ├── android-icon-144x144.png │ │ ├── android-icon-192x192.png │ │ ├── android-icon-36x36.png │ │ ├── android-icon-48x48.png │ │ ├── android-icon-72x72.png │ │ ├── android-icon-96x96.png │ │ ├── apple-icon-114x114.png │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-144x144.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-180x180.png │ │ ├── apple-icon-57x57.png │ │ ├── apple-icon-60x60.png │ │ ├── apple-icon-72x72.png │ │ ├── apple-icon-76x76.png │ │ ├── apple-icon-precomposed.png │ │ ├── apple-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── manifest.json │ │ ├── ms-icon-144x144.png │ │ ├── ms-icon-150x150.png │ │ ├── ms-icon-310x310.png │ │ └── ms-icon-70x70.png │ ├── covid.png │ ├── github.png │ ├── up_green_arrow.png │ ├── up_red_arrow.png │ └── world.png └── styles │ └── sass │ └── styles.scss ├── config └── copy-to-dist.js ├── package.json ├── postcss.config.js ├── src ├── index.html └── js │ ├── About.js │ ├── App.js │ ├── Countries.js │ ├── Country.js │ ├── CountrySelector.js │ ├── GitHub.js │ ├── Home.js │ ├── HomePageSelctor.js │ ├── IndiaDistrict.js │ ├── IndiaState.js │ ├── IndiaStateCharts.js │ ├── Information.js │ ├── News.js │ ├── NotFoundPage.js │ ├── Notification.js │ ├── World.js │ ├── actions │ ├── covidAction.js │ └── timeseriesAction.js │ ├── charts │ └── RadarCovidChart.js │ ├── covid-all │ ├── CompareWidget.js │ ├── CountryCasesWidget.js │ ├── CountryTestCase.js │ ├── OverAllWidget.js │ ├── StateIndiaMostConfirmed.js │ ├── StateIndiaMostDeaths.js │ ├── StateIndiaMostRadialSpreads.js │ ├── StateIndiaRecoveryProgress.js │ ├── TopNDeathWidget.js │ ├── TopNRecoveredWidget.js │ └── TopNTodayDeath.js │ ├── index.js │ ├── reducers │ ├── covid19Reducer.js │ ├── index.js │ └── timeseriesReducer.js │ ├── store │ ├── index.js │ └── store.js │ ├── time-series │ ├── FetchTimeSeries.js │ ├── IndiaDistrictTrend.js │ ├── TimeSeries.js │ ├── TimeSeriesBroken.js │ └── TimeSeriesPercentage.js │ ├── useFetch.js │ └── utils │ ├── color_codes.js │ ├── country_code.js │ ├── india_state_codes.js │ ├── top-headlines.json │ └── url.js ├── webpack.config.js └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "atapas", 10 | "name": "Tapas Adhikary", 11 | "avatar_url": "https://avatars1.githubusercontent.com/u/3633137?v=4", 12 | "profile": "https://tapasadhikary.com", 13 | "contributions": [ 14 | "code" 15 | ] 16 | }, 17 | { 18 | "login": "nirmalkc", 19 | "name": "Nirmal Kumar", 20 | "avatar_url": "https://avatars1.githubusercontent.com/u/6359059?v=4", 21 | "profile": "https://github.com/nirmalkc", 22 | "contributions": [ 23 | "bug" 24 | ] 25 | }, 26 | { 27 | "login": "SauravKanchan", 28 | "name": "Saurav Kanchan", 29 | "avatar_url": "https://avatars3.githubusercontent.com/u/21256638?v=4", 30 | "profile": "https://saurav.tech/", 31 | "contributions": [ 32 | "code" 33 | ] 34 | }, 35 | { 36 | "login": "NagarjunShroff", 37 | "name": "NagarjunShroff", 38 | "avatar_url": "https://avatars1.githubusercontent.com/u/37444771?v=4", 39 | "profile": "https://github.com/NagarjunShroff", 40 | "contributions": [ 41 | "code" 42 | ] 43 | } 44 | ], 45 | "contributorsPerLine": 7, 46 | "projectName": "covid-19", 47 | "projectOwner": "atapas", 48 | "repoType": "github", 49 | "repoHost": "https://github.com", 50 | "skipCi": true 51 | } 52 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ], 6 | "plugins": [ 7 | ["@babel/transform-runtime"] 8 | ] 9 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | dist 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # TypeScript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # next.js build output 62 | .next 63 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at tapas.adhikary@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tapas Adhikary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # COVID-19 World 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) 4 | 5 | 6 | COVID-19 is the infectious disease caused by the most recently discovered coronavirus. This new virus and disease were unknown before the outbreak began in Wuhan, China, in December 2019. 7 | 8 | With the oubreak world-wide and increasing number of active patients, there are many efforts to project the data in some form for people to follow and understand. 9 | 10 | `COVID-19 World` is yet another Project to build a Dashboard like app to showcase the data related to the COVID-19(Corona Virus). 11 | 12 | # See it Running 13 | 14 | `COVID-19 World` app is running as a website hosted on [![Netlify Status](https://api.netlify.com/api/v1/badges/3ce79a2b-dd74-4c1b-856b-ef5f52ed3d48/deploy-status)](https://app.netlify.com/sites/covid-19-world/deploys) 15 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fatapas%2Fcovid-19.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fatapas%2Fcovid-19?ref=badge_shield) 16 | 17 | 👉 [https://covid-19-world.netlify.com/](https://covid-19-world.netlify.com/) 18 | 19 | # Many Thanks to all the `Stargazers` who has supported this project with stars(⭐) 20 | 21 | [![Stargazers repo roster for @atapas/covid-19](https://reporoster.com/stars/atapas/covid-19)](https://github.com/atapas/covid-19/stargazers) 22 | 23 | # Analytics 24 | 25 | `COVID-19 World` provides some basic but useful analytics to understand the depth and gravity of the situation. 26 | 27 | ## Home Page [🔗](https://covid-19-world.netlify.com/home) 28 | 29 | `Home` page provides the statistics on the data from country `India`, i.e, my Country. 30 | 31 | - Total Number of Confirmed Cases 32 | - Total Number of Active Cases 33 | - Total Number of Recoverd Cases 34 | - Total Number of Deaths 35 | - Trends 36 | - Number of New Cases Found per Day 37 | - New Cases Trends - % Changes Per day 38 | - Trends Change of Confirmed vs Active vs Recovered vs Deaths 39 | - State Data Break-ups 40 | - State: Most Affected 41 | - State: Most Recovered 42 | - District Wise Data Breakups for a State 43 | 44 | ## World Page [🔗](https://covid-19-world.netlify.com/world) 45 | 46 | `World` page provides the rich features and stats about the Countries affected by the virus: 47 | 48 | - Compare Countries over the Weeks: Compare the Spreads by Selecting the Countries of your choice. The selection also gets persisted into the localstorage of the browser so that, you can montor those over times. 49 | - Countries with Overall Death Impact 50 | - Countries Recovering Well 51 | - Total Cases and Splits 52 | - Countries with maximum Deaths Today 53 | - Major Country Spreads 54 | 55 | ## Countries Page [🔗](https://covid-19-world.netlify.com/countries) 56 | 57 | `Countries` page list down all the countries affected by the Virus today. This page allows to: 58 | 59 | - Find a Specific Country by type-down search. 60 | - Select a Country to drill down on the details. 61 | - Sort the Countries based on, total cases, active cases, deaths and recovery. 62 | 63 | ## Information Page [🔗](https://covid-19-world.netlify.com/information) 64 | 65 | `Information` page provides general information about COVID-19. 66 | 67 | ## News Page [🔗](https://covid-19-world.netlify.com/news) 68 | 69 | `News` page shows the curated news about COVID-19 and Health from different publications over the globe. 70 | 71 | 72 | # To Run from the Source 73 | 74 | `COVID-19 World` is a ReactJS based project uses API from various sources to visualize and analyse the data to represent in most useful manner. Once you clone/fork the repo, you should be able to run it locally. 75 | 76 | Make sure, you have NodeJS installed. Preffered Version of nodeJs is >=12.7.0 77 | 78 | With Yarn, Do the followings: 79 | 80 | - `yarn install`: Install the Projcect Dependencies 81 | - `yarn start`: Start the app in dev mode. The app will be available on [https://localhost:4000](https://localhost:4000) 82 | - `yarn build`: Build the app for production. 83 | 84 | With NPM, Do the followings: 85 | 86 | - `npm install`: Install the Projcect Dependencies 87 | - `npm run start`: Start the app in dev mode. The app will be available on [https://localhost:4000](https://localhost:4000) 88 | - `npm run build`: Build the app for production. 89 | 90 | # Credits and Motivations 91 | 92 | Only motivation behind building this app was to kill time at home over a Long Weekend. 😏 93 | 94 | My sincere thanks to followings 👍: 95 | 96 | - [Coronavirus NovelCOVID API](https://github.com/NovelCOVID/API) 97 | - [COVID Time-Series API(Pomber)](https://github.com/pomber/COVID19) 98 | - Corona State Data(India) 99 | - [API for News](https://newsapi.org/) 100 | 101 | # Technologies 102 | 103 | This app is built from the scratch using following User Interface Technologies: 104 | 105 | - [ReactJs](https://reactjs.org/) 106 | - [Bootstrap](https://react-bootstrap.netlify.com/) 107 | - [Recharts](http://recharts.org/en-US/) 108 | 109 | # License 110 | 111 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fatapas%2Fcovid-19.svg?type=large)](https://app.fossa.io/reports/970db5be-b904-4b5c-acea-1c708a0e92b8) 112 | 113 | # 🙏 Stay Home, Stay Safe! 🙏 114 | 115 | Contact [https://www.tapasadhikary.com](https://www.tapasadhikary.com) for any further queries. 116 | 117 | ## Contributors ✨ 118 | 119 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 |

Tapas Adhikary

💻

Nirmal Kumar

🐛

Saurav Kanchan

💻

NagarjunShroff

💻
132 | 133 | 134 | 135 | 136 | 137 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 138 | -------------------------------------------------------------------------------- /_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-144x144.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-192x192.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-36x36.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-48x48.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-72x72.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/android-icon-96x96.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-114x114.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-120x120.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-144x144.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-152x152.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-180x180.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-57x57.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-60x60.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-72x72.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-76x76.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon-precomposed.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/apple-icon.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /assets/images/add_to_hs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/favicon-16x16.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/favicon-32x32.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/favicon-96x96.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/favicon.ico -------------------------------------------------------------------------------- /assets/images/add_to_hs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "\/android-icon-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image\/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "\/android-icon-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image\/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "\/android-icon-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image\/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "\/android-icon-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image\/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "\/android-icon-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image\/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "\/android-icon-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image\/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /assets/images/add_to_hs/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/ms-icon-144x144.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/ms-icon-150x150.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/ms-icon-310x310.png -------------------------------------------------------------------------------- /assets/images/add_to_hs/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/add_to_hs/ms-icon-70x70.png -------------------------------------------------------------------------------- /assets/images/covid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/covid.png -------------------------------------------------------------------------------- /assets/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/github.png -------------------------------------------------------------------------------- /assets/images/up_green_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/up_green_arrow.png -------------------------------------------------------------------------------- /assets/images/up_red_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/up_red_arrow.png -------------------------------------------------------------------------------- /assets/images/world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atapas/covid-19/fe48f7675e3f83c12041bff38baf07c879c08136/assets/images/world.png -------------------------------------------------------------------------------- /assets/styles/sass/styles.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | font-size: 14px; 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | .regular-checkbox { 9 | width: 25px; 10 | height: 25px; 11 | } 12 | 13 | .world { 14 | padding: 10px; 15 | } 16 | 17 | .navbar .navbar-nav .nav-link { 18 | background-color: #333; 19 | border: 1px solid #333; 20 | border-radius: 9px; 21 | color: #e3e3e3; 22 | margin-right: 6px; 23 | } 24 | 25 | .navbar .navbar-nav .nav-link:hover { 26 | color: #FFFFFF; 27 | text-decoration: underline; 28 | } 29 | 30 | .worldData .legends .badge { 31 | padding: 6px; 32 | margin-right: 3px; 33 | } 34 | 35 | .worldData .legends { 36 | margin-left: 17%; 37 | } 38 | 39 | .custom-tooltip { 40 | padding: 10px; 41 | background-color: #FFF; 42 | border: 1px solid #333; 43 | border-radius: 3px; 44 | } 45 | 46 | .world .inner .search{ 47 | padding: 10px; 48 | } 49 | 50 | .world .worldCharts { 51 | margin-bottom: 30px; 52 | } 53 | 54 | .countries { 55 | padding: 10px; 56 | } 57 | 58 | .countries .inner { 59 | padding: 10px; 60 | } 61 | 62 | .countries .inner .sort-by SELECT { 63 | margin-left: 3px; 64 | } 65 | 66 | .countries .inner .sort-by { 67 | margin-bottom: 8px; 68 | } 69 | 70 | .countries .inner .search{ 71 | margin-bottom: 10px; 72 | } 73 | 74 | .countries .inner .countryCapsules { 75 | padding-left: 3px; 76 | padding-top: 3px; 77 | padding-right: 3px; 78 | padding-bottom: 3px; 79 | width: 220px; 80 | margin: 3px; 81 | height: 60px; 82 | background-color: #e3e3e3!important; 83 | } 84 | 85 | .countries .inner .countryCapsules .imageCountry { 86 | float: left; 87 | } 88 | 89 | .countries .inner .countryCapsules .imageCountry img { 90 | margin-right: 5px; 91 | } 92 | 93 | .countries .inner .countryCapsules .imageCountry span { 94 | margin-right: 2px; 95 | font-size: 14px; 96 | } 97 | 98 | .world .compare-widget .countryCapsules { 99 | padding: 3px; 100 | margin-left: 4px; 101 | margin-right: 4px; 102 | } 103 | 104 | .world .compare-widget .countryCapsules .imageCountry span { 105 | margin-left: 3px; 106 | } 107 | 108 | .world .compare-widget .country-select { 109 | margin-left: 5px; 110 | } 111 | 112 | .world .compare-widget .country-select .icon{ 113 | color: #FFFFFF; 114 | } 115 | 116 | .countryHeadline .country { 117 | padding: 0px; 118 | } 119 | 120 | .country { 121 | padding: 10px; 122 | } 123 | 124 | .country .flag { 125 | margin-right: 5px; 126 | } 127 | 128 | .country .stat { 129 | padding: 10px; 130 | } 131 | 132 | .country .stat .badge { 133 | padding: 20px; 134 | max-width: 230px; 135 | min-width: 200px; 136 | height: 200px; 137 | margin-left: 5%; 138 | } 139 | 140 | .country .stat .badge .label { 141 | font-size: 30px; 142 | } 143 | .country .stat .badge .value { 144 | font-size: 40px; 145 | } 146 | 147 | .country .stat .badge .extra { 148 | font-size: 13px; 149 | padding: 10px; 150 | } 151 | 152 | .country .stat .badge .perct { 153 | font-size: 20px; 154 | padding: 8px; 155 | } 156 | 157 | .country .trends { 158 | margin-top: 20px; 159 | } 160 | 161 | .country .trends .timeseries .chart { 162 | padding-top: 20px; 163 | } 164 | 165 | .country .trends .timeseries .chart H2{ 166 | margin-left: 30px; 167 | margin-bottom: 14px; 168 | } 169 | 170 | .information { 171 | padding: 10px; 172 | } 173 | 174 | .information .heading H2 IMG { 175 | margin-right: 6px; 176 | } 177 | 178 | .indiaState { 179 | margin-top: 20px; 180 | } 181 | 182 | .about .link{ 183 | color: #e3e3e3; 184 | } 185 | 186 | .about .link:hover{ 187 | color: #ffffff; 188 | } 189 | 190 | .india-state-charts { 191 | margin-top: 20px; 192 | padding: 0px; 193 | } 194 | 195 | .type-btn-grp { 196 | float: right; 197 | } 198 | 199 | .type-btn-grp .btn { 200 | border-color: #5A6268; 201 | } 202 | 203 | .type-btn-grp .selected { 204 | background-color: #000000; 205 | color: #FFFFFF; 206 | border-color: #000000; 207 | box-shadow: 2px solid #000000; 208 | } 209 | 210 | .expandedRow { 211 | background-color: #FFFFFF!important; 212 | } 213 | 214 | .expandedRow :hover { 215 | background-color: #FFFFFF!important; 216 | } 217 | 218 | .expandedRow .district UL LI { 219 | font-size: 16px; 220 | list-style: none; 221 | padding: 5px; 222 | border: 1px solid #F2F2F2; 223 | } 224 | 225 | .expandedRow .district UL LI .notes { 226 | margin-left: 20px; 227 | padding: 5px; 228 | color: #DC3545; 229 | } 230 | 231 | .expandedRow .district UL LI .notes .icon { 232 | margin-right: 5px; 233 | } 234 | 235 | .select-country-modal .header .icon{ 236 | margin-right: 5px; 237 | } 238 | 239 | .select-country-modal .content LI{ 240 | list-style: none; 241 | margin-top: 5px; 242 | } 243 | 244 | .select-country-modal INPUT.filterbox { 245 | margin-bottom: 10px; 246 | } 247 | 248 | .select-country-modal .content { 249 | max-height: 300px; 250 | overflow-y: auto; 251 | padding: 8px; 252 | } 253 | 254 | .time-series-percentage-cases { 255 | padding-top: 20px; 256 | } 257 | 258 | /* Notification Component Styles */ 259 | 260 | .notification-container { 261 | margin-right: 15px; 262 | } 263 | 264 | /* Notifications */ 265 | 266 | .notification { 267 | display: inline-block; 268 | position: relative; 269 | padding: 6px; 270 | background: #282828; 271 | color: #FFFFFF; 272 | border-radius: 45px; 273 | font-size: 1.3em; 274 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); 275 | cursor: pointer; 276 | } 277 | 278 | .notification::before, 279 | .notification::after { 280 | color: #fff; 281 | text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); 282 | } 283 | 284 | .notification::before { 285 | display: block; 286 | 287 | font-family: "FontAwesome"; 288 | transform-origin: top center; 289 | } 290 | 291 | .notification::after { 292 | font-family: Arial; 293 | font-size: 12px; 294 | font-weight: 700; 295 | position: absolute; 296 | top: -9px; 297 | right: -15px; 298 | padding: 5px 8px; 299 | line-height: 100%; 300 | border: 2px #fff solid; 301 | border-radius: 60px; 302 | background: #db3434; 303 | opacity: 0; 304 | content: attr(data-count); 305 | opacity: 0; 306 | transform: scale(0.5); 307 | transition: transform, opacity; 308 | transition-duration: 0.3s; 309 | transition-timing-function: ease-out; 310 | } 311 | 312 | .notification.notify::before { 313 | animation: ring 1.5s ease; 314 | } 315 | 316 | .notification.show-count::after { 317 | transform: scale(1); 318 | opacity: 1; 319 | } 320 | 321 | .notification-info-panel { 322 | height: 500px; 323 | overflow-y: auto; 324 | padding: 0; 325 | } 326 | 327 | .notification-info-panel .notification-message { 328 | list-style: none; 329 | padding: 4px; 330 | background-color: #ebebeb; 331 | margin-bottom: 3px; 332 | border: 1px solid #ececec; 333 | border-radius: 8px; 334 | } 335 | 336 | .notification-info-panel .notification-message .timestamp { 337 | margin-bottom: 2px; 338 | font-size: 13px; 339 | font-weight: 600; 340 | } 341 | 342 | .notification-info-panel .notification-message .content { 343 | font-size: 17px; 344 | } 345 | 346 | .notification-info-panel .notification-message.unread { 347 | background-color: #17A2B8; 348 | color: #FFFFFF; 349 | } 350 | 351 | 352 | -------------------------------------------------------------------------------- /config/copy-to-dist.js: -------------------------------------------------------------------------------- 1 | // process.chdir('./back-end'); 2 | // require('child_process').exec('sails lift'); 3 | 4 | const fs = require('fs'); 5 | 6 | // _redirects will be created or overwritten by default. 7 | fs.copyFile('_redirects', './dist/_redirects', (err) => { 8 | if (err) throw err; 9 | console.log('_redirects was copied to dist folder!'); 10 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-4-quickstart", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "npm run open:client", 8 | "open:client": "webpack-dev-server --mode development --open", 9 | "build": "webpack --mode production", 10 | "copy": "node ./config/copy-to-dist.js", 11 | "prod": "npm run build && npm run copy" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "MIT", 16 | "devDependencies": { 17 | "@babel/core": "^7.5.5", 18 | "@babel/plugin-transform-runtime": "^7.5.5", 19 | "@babel/preset-env": "^7.5.5", 20 | "@babel/preset-react": "^7.0.0", 21 | "autoprefixer": "^9.6.1", 22 | "babel-loader": "^8.0.6", 23 | "css-loader": "^3.2.0", 24 | "cssnano": "^4.1.10", 25 | "file-loader": "^4.2.0", 26 | "html-loader": "^0.5.5", 27 | "html-webpack-plugin": "^3.2.0", 28 | "mini-css-extract-plugin": "^0.8.0", 29 | "node-sass": "^4.12.0", 30 | "postcss-loader": "^3.0.0", 31 | "react": "^16.9.0", 32 | "react-dom": "^16.9.0", 33 | "sass-loader": "^8.0.0", 34 | "webpack": "^4.41.2", 35 | "webpack-cli": "^3.3.7", 36 | "webpack-dev-server": "^3.8.0" 37 | }, 38 | "dependencies": { 39 | "@babel/runtime": "^7.5.5", 40 | "@fortawesome/fontawesome-free": "^5.13.0", 41 | "ag-grid-community": "^23.0.1", 42 | "ag-grid-react": "^23.0.0", 43 | "bootstrap": "^4.4.1", 44 | "cross-env": "^7.0.2", 45 | "moment": "^2.24.0", 46 | "randomcolor": "^0.5.4", 47 | "react-bootstrap": "^1.0.0-beta.17", 48 | "react-currency-format": "^1.0.0", 49 | "react-dom-factories": "^1.0.2", 50 | "react-loader-spinner": "^3.1.5", 51 | "react-moment": "^0.9.7", 52 | "react-redux": "^7.2.0", 53 | "react-router-dom": "^5.1.2", 54 | "reactjs-localstorage": "^0.0.8", 55 | "recharts": "^1.8.5", 56 | "redux": "^4.0.5", 57 | "redux-thunk": "^2.3.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | // It is handy to not have those transformations while we developing 2 | if(process.env.NODE_ENV === 'production') { 3 | module.exports = { 4 | plugins: [ 5 | require('autoprefixer'), 6 | require('cssnano'), 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | COVID-19 World at a Glance 24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /src/js/About.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, { useState } from 'react'; 8 | 9 | import Modal from 'react-bootstrap/Modal'; 10 | import Button from 'react-bootstrap/Button' 11 | 12 | const About = () => { 13 | 14 | const [show, setShow] = useState(false); 15 | const handleClose = () => setShow(false); 16 | const handleShow = () => setShow(true); 17 | 18 | return ( 19 |
20 | 23 | 24 | 25 | 26 | About 27 | 28 | 29 |

🙏 Stay Home, Stay Safe! 🙏

30 |
31 |

32 | Initially, the only motivation behind building this app was to kill time at home over a weekend 😏. 33 | As the days passed, I started realizing that, it takes lot to provide some information to clearly understand what 34 | is going on! 35 |
36 | Hence the effort started to put some data analytics together from various data sources to present 37 | meaningful information. 38 |

39 | 40 | My sincere thanks to followings 👍: 41 | 63 |
64 |

💻 Technologies 💻

65 |

66 | This app is built from the scratch using following User Interface Technologies: 67 |

81 |

82 |
83 | 84 | Contact me 85 | for any further questions. 86 | 87 |
88 |
89 |
90 | ); 91 | }; 92 | 93 | export default About; -------------------------------------------------------------------------------- /src/js/App.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | import { 9 | BrowserRouter as Router, 10 | Route, 11 | Switch, 12 | Link 13 | } from 'react-router-dom'; 14 | import { useDispatch } from 'react-redux'; 15 | import Navbar from 'react-bootstrap/Navbar'; 16 | import Nav from 'react-bootstrap/Nav'; 17 | import Form from 'react-bootstrap/Form'; 18 | import FormControl from 'react-bootstrap/FormControl'; 19 | import Button from 'react-bootstrap/Button'; 20 | 21 | import Loader from 'react-loader-spinner'; 22 | 23 | import { useFetch } from './useFetch'; 24 | 25 | import Home from './Home'; 26 | import World from './World'; 27 | import Countries from './Countries'; 28 | import Country from './Country'; 29 | import NotFoundPage from './NotFoundPage'; 30 | import News from './News'; 31 | import Information from './Information'; 32 | import About from './About'; 33 | import GitHub from './GitHub'; 34 | import Notification from './Notification'; 35 | 36 | import { registerCovid19Data } from './actions/covidAction'; 37 | 38 | import * as covid from '../../assets/images/covid.png'; 39 | 40 | const App = () => { 41 | const dispatch = useDispatch(); 42 | const [countryCoronaData, countryCoronaDataLoading] = useFetch( 43 | "https://corona.lmao.ninja/v2/countries" 44 | ); 45 | 46 | if (!countryCoronaDataLoading) { 47 | dispatch(registerCovid19Data(countryCoronaData)); 48 | } 49 | 50 | return ( 51 | 52 | 53 | 54 |
55 | 56 | 57 | {covid}{' '} 64 | COVID-19 65 | 66 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 81 | countryCoronaDataLoading ? 82 | : 89 | } 90 | /> 91 | 93 | countryCoronaDataLoading ? 94 | : 101 | } 102 | /> 103 | 105 | countryCoronaDataLoading ? 106 | : 113 | } 114 | /> 115 | 117 | countryCoronaDataLoading ? 118 | : 125 | } 126 | /> 127 | 129 | countryCoronaDataLoading ? 130 | : 137 | } /> 138 | 139 | 140 | 141 | 142 | 143 | 144 | } /> 145 | 146 |
147 |
148 | ); 149 | }; 150 | export default App; 151 | 152 | -------------------------------------------------------------------------------- /src/js/Countries.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { useSelector } from 'react-redux'; 3 | import Container from 'react-bootstrap/Container'; 4 | import Row from 'react-bootstrap/Row'; 5 | import Col from 'react-bootstrap/Col'; 6 | import Form from 'react-bootstrap/Form'; 7 | /* 8 | * Created on Sun Apr 12 2020 9 | * 10 | * Copyright (c) 2020 https://tapasadhikary.com 11 | */ 12 | 13 | import FormControl from 'react-bootstrap/FormControl'; 14 | import FetchTimeSeries from './time-series/FetchTimeSeries'; 15 | 16 | const Countries = props => { 17 | 18 | const covid19Data = useSelector(state => state.covid19); 19 | let data = covid19Data.filter(elem => { 20 | return elem.country !== 'World'; 21 | }); 22 | const [countries, setCountries] = useState([]); 23 | const [filteredCountries, setFilteredCountries] = useState([]); 24 | const [sortBy, setSortBy] = useState('active'); 25 | 26 | // const SORT_BY = 'cases'; 27 | 28 | useEffect(() => { 29 | let sorted = data.sort((a,b) => b[sortBy] - a[sortBy]); 30 | let mappedCountries = sorted.map(elem => { 31 | return elem.country 32 | }) 33 | setCountries(mappedCountries); 34 | setFilteredCountries(mappedCountries); 35 | }, [sortBy]); 36 | 37 | 38 | 39 | const handleFind = event => { 40 | event.preventDefault(); 41 | let filtered = countries.filter(elem => { 42 | return elem.toLowerCase().includes(event.target.value.toLowerCase()); 43 | 44 | }); 45 | setFilteredCountries(filtered); 46 | } 47 | 48 | const handleSelect = event => { 49 | let selectedSortVal = event.target.value; 50 | if ( selectedSortVal == 'Active') { 51 | setSortBy('active'); 52 | }else if ( selectedSortVal == 'Total') { 53 | setSortBy('cases'); 54 | }else if ( selectedSortVal == 'Recovery') { 55 | setSortBy('recovered'); 56 | }else if ( selectedSortVal == 'Deaths') { 57 | setSortBy('deaths'); 58 | }else if ( selectedSortVal == 'New Cases') { 59 | setSortBy('todayCases'); 60 | }else if ( selectedSortVal == 'New Deaths') { 61 | setSortBy('todayDeaths'); 62 | } 63 | } 64 | 65 | return( 66 |
67 | 68 | 69 | 70 |
71 | 72 | Sorted By: 73 | handleSelect(event)} style={{cursor:'pointer'}}> 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
83 | 84 |
85 | 86 | 87 | handleFind(event)} /> 92 | 93 | 94 | 95 | {filteredCountries.map((country) => 96 | 97 | 98 | 99 | )} 100 | 101 |
102 |
103 | 104 | ) 105 | }; 106 | 107 | export default Countries; 108 | -------------------------------------------------------------------------------- /src/js/Country.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Created on Sun Apr 12 2020 4 | * 5 | * Copyright (c) 2020 https://tapasadhikary.com 6 | */ 7 | 8 | import React, { useState, useEffect } from 'react'; 9 | import { useSelector } from 'react-redux'; 10 | import Container from 'react-bootstrap/Container'; 11 | import Row from 'react-bootstrap/Row'; 12 | import Col from 'react-bootstrap/Col'; 13 | import Badge from 'react-bootstrap/Badge' 14 | import Button from 'react-bootstrap/Button'; 15 | import CurrencyFormat from 'react-currency-format'; 16 | 17 | import { useFetch } from './useFetch'; 18 | import COUNTRY_CODES from './utils/country_code'; 19 | import TimeSeries from './time-series/TimeSeries'; 20 | import IndiaState from './IndiaState'; 21 | import IndiaStateCharts from './IndiaStateCharts'; 22 | import HomePageSelector from './HomePageSelctor'; 23 | import {reactLocalStorage} from 'reactjs-localstorage'; 24 | import Loader from 'react-loader-spinner'; 25 | 26 | const Country = props => { 27 | const queriedCountry = props.location ? 28 | new URLSearchParams(props.location.search).get('name') : 29 | props.countryName; 30 | const [indiaData, indiaDataLoading] = useFetch('https://api.covid19india.org/data.json'); 31 | const [countryName, setCountryName] = useState( 32 | queriedCountry 33 | ); 34 | 35 | const countryCoronaData = useSelector(state => state.covid19); 36 | const getCountryCode = country => { 37 | let selectedCountry = COUNTRY_CODES.filter(elem => { 38 | return elem.name === country; 39 | }); 40 | let countryCode = ''; 41 | if (selectedCountry.length > 0) { 42 | countryCode = selectedCountry[0]['alpha2code']; 43 | } 44 | return countryCode; 45 | } 46 | 47 | let covid = countryCoronaData.filter(elem => { 48 | return elem.country.toLowerCase() === countryName.toLowerCase(); 49 | }); 50 | 51 | let stateData = []; 52 | let inidiaTotalData = {} 53 | if (!indiaDataLoading) { 54 | let stateWise = indiaData['statewise']; 55 | inidiaTotalData = stateWise[0]; 56 | stateData = stateWise.filter((elem, i) => i > 0); 57 | } 58 | 59 | const getTotalValue = type => { 60 | if (type === 'confirmed') { 61 | if (countryName === 'India') { 62 | if (!indiaDataLoading) { 63 | return inidiaTotalData.confirmed; 64 | } else { 65 | return "..."; 66 | } 67 | } else { 68 | return covid[0].cases; 69 | } 70 | 71 | } else if (type === 'active') { 72 | if (countryName === 'India') { 73 | if (!indiaDataLoading) { 74 | return inidiaTotalData.active; 75 | } else { 76 | return "..."; 77 | } 78 | } else { 79 | return covid[0].active; 80 | } 81 | 82 | } else if (type === 'recovered') { 83 | if (countryName === 'India') { 84 | if (!indiaDataLoading) { 85 | return inidiaTotalData.recovered; 86 | } else { 87 | return "..."; 88 | } 89 | } else { 90 | return covid[0].recovered; 91 | } 92 | 93 | } else if (type === 'deaths') { 94 | if (countryName === 'India') { 95 | if (!indiaDataLoading) { 96 | return inidiaTotalData.deaths; 97 | } else { 98 | return "..."; 99 | } 100 | } else { 101 | return covid[0].deaths; 102 | } 103 | } 104 | } 105 | 106 | const getIncreasdValue = type => { 107 | if (countryName === 'India') { 108 | if (!indiaDataLoading) { 109 | if (type === 'confirmed') { 110 | return getFormattedIncreased(inidiaTotalData.deltaconfirmed); 111 | } else if (type === 'active') { 112 | return getFormattedIncreased(inidiaTotalData.deltaconfirmed); 113 | } else if (type === 'recovered') { 114 | return getFormattedIncreased(inidiaTotalData.deltarecovered); 115 | } else if (type === 'deaths') { 116 | return getFormattedIncreased(inidiaTotalData.deltadeaths); 117 | } 118 | } 119 | } else { 120 | if (type === 'confirmed') { 121 | return getFormattedIncreased(covid[0].todayCases); 122 | } else if (type === 'active') { 123 | return getFormattedIncreased(covid[0].todayCases); 124 | } else if (type === 'deaths') { 125 | return getFormattedIncreased(covid[0].todayDeaths); 126 | } 127 | } 128 | } 129 | 130 | const getFormattedIncreased = value => { 131 | if (value > 0) { 132 | return `[ Today: +${value} ]`; 133 | } else { 134 | return `[ Today: 0 ]`; 135 | } 136 | } 137 | 138 | const getLastInfoUpdatedTime = () => { 139 | if (countryName === 'India') { 140 | if (!indiaDataLoading) { 141 | return indiaData.key_values[0].lastupdatedtime; 142 | } 143 | } 144 | } 145 | 146 | const getPercentage = type => { 147 | if (type === 'active') { 148 | if (countryName === 'India') { 149 | if (!indiaDataLoading) { 150 | let calc = (inidiaTotalData.active/inidiaTotalData.confirmed) * 100; 151 | return `${ calc.toFixed(2) }%`; 152 | } else { 153 | return "..."; 154 | } 155 | } else { 156 | let calc = (covid[0].active/covid[0].cases) * 100; 157 | return `${ calc.toFixed(2) }%`; 158 | } 159 | 160 | } else if (type === 'recovered') { 161 | if (countryName === 'India') { 162 | if (!indiaDataLoading) { 163 | let calc = (inidiaTotalData.recovered / inidiaTotalData.confirmed) * 100; 164 | return `${ calc.toFixed(2) }%`; 165 | } else { 166 | return "..."; 167 | } 168 | } else { 169 | let calc = (covid[0].recovered/covid[0].cases) * 100; 170 | return `${ calc.toFixed(2) }%`; 171 | } 172 | 173 | } else if (type === 'deaths') { 174 | if (countryName === 'India') { 175 | if (!indiaDataLoading) { 176 | let calc = (inidiaTotalData.deaths/inidiaTotalData.confirmed) * 100; 177 | return `${ calc.toFixed(2) }%`; 178 | } else { 179 | return "..."; 180 | } 181 | } else { 182 | let calc = (covid[0].deaths/covid[0].cases) * 100; 183 | return `${ calc.toFixed(2) }%`; 184 | } 185 | } 186 | } 187 | 188 | const updateCountry = country => { 189 | setCountryName(country); 190 | reactLocalStorage.setObject('country_selection', country); 191 | } 192 | 193 | return( 194 | 195 | 196 | 197 |

198 | { 199 | getCountryCode(countryName) !== '' ? 200 | {countryName} : null 204 | } 205 | {countryName} 206 | 209 |

210 | 211 | 212 |
213 | { 214 | covid.length > 0 ? 215 | 216 | 217 | 218 |

Total

219 |
{value}
} /> 224 |
{getIncreasdValue('confirmed')}
225 | 226 |
227 | 228 | 229 | 230 |

Active

231 |
{getPercentage('active')}
232 |
{value}
} /> 237 |
{getIncreasdValue('active')}
238 | 239 | 240 |
241 | 242 | 243 | 244 |

Recovered

245 |
{getPercentage('recovered')}
246 |
{value}
} /> 251 | 252 | { 253 | (!indiaDataLoading && countryName === 'India') ? 254 |
{getIncreasdValue('recovered')}
255 | : null 256 | } 257 | 258 |
259 | 260 | 261 | 262 |

Deaths

263 |
{getPercentage('deaths')}
264 |
{value}
} /> 269 | 270 |
{getIncreasdValue('deaths')}
271 |
272 | 273 |
: null 274 | } 275 | 276 | 277 | { 278 | indiaDataLoading ? 279 | : 285 | (countryName === 'India') ? 286 | <> 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | : 304 | 305 | 306 | 307 | 308 | 309 | 310 | } 311 | 312 |
313 | ) 314 | }; 315 | 316 | export default Country; -------------------------------------------------------------------------------- /src/js/CountrySelector.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Created on Sun Apr 12 2020 4 | * 5 | * Copyright (c) 2020 https://tapasadhikary.com 6 | */ 7 | 8 | import React, { useState, useEffect } from 'react'; 9 | import Modal from 'react-bootstrap/Modal'; 10 | import Button from 'react-bootstrap/Button'; 11 | import FormControl from 'react-bootstrap/FormControl'; 12 | import { useSelector } from 'react-redux'; 13 | 14 | import FetchTimeSeries from './time-series/FetchTimeSeries'; 15 | 16 | const Checkbox = ({ type = 'checkbox', name, checked = false, onChange, className = 'regular-checkbox' }) => { 17 | return () 18 | } 19 | 20 | const CountrySelector = ({ preSelected , update}) => { 21 | const [checkedItems, setCheckedItems] = useState(preSelected); 22 | const [show, setShow] = useState(false); 23 | const covid19Data = useSelector(state => state.covid19); 24 | const [filteredCountries, setFilteredCountries] = useState([]); 25 | const [allCountries, setAllCountries] = useState([]); 26 | 27 | useEffect(() => { 28 | let data = covid19Data.filter(elem => { 29 | return elem.country !== 'World'; 30 | }); 31 | 32 | let sortedCountries = data.sort((a,b) => b.cases - a.cases); 33 | 34 | let allCountries = sortedCountries.map(elem => { 35 | return { 'name': elem.country }; 36 | }); 37 | setAllCountries(allCountries); 38 | setFilteredCountries(allCountries); 39 | }, []); 40 | 41 | const handleSelect = () => { 42 | setShow(false); 43 | setFilteredCountries(allCountries); 44 | update(checkedItems); 45 | } 46 | 47 | const handleCancel = () => { 48 | setShow(false); 49 | setCheckedItems(preSelected); 50 | setFilteredCountries(allCountries); 51 | // update(checkedItems); 52 | } 53 | 54 | const handleShow = () => setShow(true); 55 | 56 | const handleChange = (event) => { 57 | let updated = { ...checkedItems, [event.target.name]: event.target.checked }; 58 | let temp = JSON.parse(JSON.stringify(updated)); 59 | // updating an object instead of a Map 60 | setCheckedItems(temp); 61 | } 62 | 63 | const handleFind = event => { 64 | event.preventDefault(); 65 | let filtered = allCountries.filter(elem => { 66 | return elem.name.toLowerCase().includes(event.target.value.toLowerCase()); 67 | 68 | }); 69 | setFilteredCountries(filtered); 70 | } 71 | 72 | const clearSelections = () => { 73 | console.log('Clear Slections'); 74 | setCheckedItems([]); 75 | } 76 | 77 | 78 | return ( 79 | <> 80 | 85 | 86 | 87 | 88 | 89 | Select Countries to Compare 90 | 91 | 92 | 93 | 94 | 100 | handleFind(event)} 105 | className="filterbox"/> 106 |
    107 | { 108 | filteredCountries.map(item => ( 109 |
  • 110 | 111 |
    112 | 116 |
    117 |
  • 118 | )) 119 | } 120 |
121 |
122 | 123 | 126 | 129 | 130 |
131 | 132 | 133 | ) 134 | }; 135 | 136 | export default CountrySelector; -------------------------------------------------------------------------------- /src/js/GitHub.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Created on Sun Apr 13 2020 4 | * 5 | * Copyright (c) 2020 https://tapasadhikary.com 6 | */ 7 | 8 | import React from 'react'; 9 | 10 | import * as github from '../../assets/images/github.png'; 11 | 12 | const GitHub = () => { 13 | 14 | return( 15 | 16 | github 17 | 18 | ) 19 | }; 20 | 21 | export default GitHub; -------------------------------------------------------------------------------- /src/js/Home.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | 9 | import Container from 'react-bootstrap/Container'; 10 | import Row from 'react-bootstrap/Row'; 11 | import Col from 'react-bootstrap/Col'; 12 | import Country from './Country'; 13 | 14 | import {reactLocalStorage} from 'reactjs-localstorage'; 15 | 16 | const Home = props => { 17 | 18 | const countryNameFromStorage = reactLocalStorage.getObject('country_selection'); 19 | 20 | let countryName = Object.keys(countryNameFromStorage).length > 0 ? 21 | countryNameFromStorage : 22 | 'India'; 23 | return( 24 | <> 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ) 34 | }; 35 | 36 | export default Home; -------------------------------------------------------------------------------- /src/js/HomePageSelctor.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import Modal from 'react-bootstrap/Modal'; 3 | import Button from 'react-bootstrap/Button'; 4 | import FormControl from 'react-bootstrap/FormControl'; 5 | import { useSelector } from 'react-redux'; 6 | import FetchTimeSeries from './time-series/FetchTimeSeries'; 7 | 8 | 9 | 10 | 11 | const HomePageSelector = ({ preSelected , update}) => { 12 | 13 | const country = preSelected; 14 | const [show, setShow] = useState(false); 15 | const [allCountries, setAllCountries] = useState([]); 16 | const covid19Data = useSelector(state => state.covid19); 17 | const [selectedCountry, setSelectedCountry] = useState({ [country] : true}); 18 | const [countryName, setCountryName] = useState(country); 19 | const [filteredCountries, setFilteredCountries] = useState([]); 20 | 21 | const Checkbox = ({ type = 'radio', name, checked = false, onChange, className = 'regular-checkbox' }) => { 22 | return () 23 | }; 24 | 25 | useEffect(() => { 26 | let data = covid19Data && covid19Data.filter(elem => { 27 | return elem.country !== 'World'; 28 | }); 29 | 30 | let sortedCountries = data.sort((a, b) => b.cases - a.cases); 31 | 32 | let allCountries = sortedCountries.map(elem => { 33 | return { 'name': elem.country }; 34 | }); 35 | setAllCountries(allCountries); 36 | setFilteredCountries(allCountries); 37 | 38 | }, []); 39 | 40 | 41 | const handleShow = () => setShow(true); 42 | 43 | const handleChange = (event) => { 44 | let updated = { [event.target.name]: event.target.checked }; 45 | setSelectedCountry(JSON.parse(JSON.stringify(updated))); 46 | setCountryName(event.target.name); 47 | } 48 | 49 | const handleFind = event => { 50 | event.preventDefault(); 51 | let filtered = allCountries.filter(elem => { 52 | return elem.name.toLowerCase().includes(event.target.value.toLowerCase()); 53 | 54 | }); 55 | setFilteredCountries(filtered); 56 | } 57 | 58 | const handleCancel = () => { 59 | setShow(false); 60 | setSelectedCountry(country ? { [country] : true} : {}); 61 | setFilteredCountries(allCountries); 62 | } 63 | 64 | const updateLocalStore = () => { 65 | update(countryName); 66 | setShow(false); 67 | setFilteredCountries(allCountries); 68 | }; 69 | 70 | return (<> 71 | 76 | 77 | 78 | 79 | 80 | Select Your Home Country 81 | 82 | 83 | 84 | 85 |
    86 | handleFind(event)} 91 | className="filterbox" /> 92 | { 93 | filteredCountries.map(item => ( 94 |
  • 95 | 96 |
    97 | 102 |
    103 |
  • 104 | )) 105 | } 106 |
107 |
108 | 109 | 112 | 115 | 116 |
117 | ); 118 | 119 | 120 | }; 121 | 122 | 123 | export default HomePageSelector; -------------------------------------------------------------------------------- /src/js/IndiaDistrict.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Button from 'react-bootstrap/Button'; 3 | 4 | import red_up_arrow from '../../assets/images/up_red_arrow.png'; 5 | import green_up_arrow from '../../assets/images/up_green_arrow.png'; 6 | 7 | import IndiaDistrictTrend from './time-series/IndiaDistrictTrend'; 8 | import Table from 'react-bootstrap/Table'; 9 | 10 | const IndiaDistrict = props => { 11 | const data = props.districtData; 12 | // const districtTrend = props.districtTrend; 13 | const districts = Object.keys(data).sort((a, b) => data[b].delta.confirmed - data[a].delta.confirmed); 14 | const [expandedRows, setExpandedRows] = useState([]); 15 | const [expandDistrict, setExpandDistrict] = useState({}); 16 | // const [districtTrendDetails, setDistrictTrendDetails] = useState(); 17 | 18 | /*const handleExpandRow = (trendDetails, district) => { 19 | const currentExpandedRows = expandedRows; 20 | const isRowCurrentlyExpanded = currentExpandedRows.includes(district); 21 | setDistrictTrendDetails(trendDetails); 22 | 23 | let tempState = {}; 24 | if (isRowCurrentlyExpanded) { 25 | let obj = {}; 26 | obj[district] = false; 27 | tempState = Object.assign({}, obj); 28 | 29 | } else { 30 | let obj = {}; 31 | obj[district] = true; 32 | tempState = Object.assign({}, obj); 33 | } 34 | 35 | setExpandDistrict(tempState) 36 | 37 | const newExpandedRows = isRowCurrentlyExpanded ? 38 | currentExpandedRows.filter(dist => dist !== district) : 39 | currentExpandedRows.concat(district); 40 | 41 | setExpandedRows(newExpandedRows); 42 | }*/ 43 | 44 | 45 | return ( 46 | 47 | <> 48 | 49 | 50 | {districts.map((name) => 51 | <> 52 | 53 | 📣 {name}: {data[name]['confirmed']} 54 | 55 | 56 | Active: {data[name]['active']} 57 | {data[name]['delta']['confirmed'] > 0 58 | ? 59 | 60 | {' '}[ {data[name]['delta']['confirmed']}] 61 | 62 | : null 63 | } 64 | 65 | 66 | Recovered: {data[name]['recovered']} 67 | {data[name]['delta']['recovered'] > 0 68 | ? 69 | 70 | {' '}[ {data[name]['delta']['recovered']}] 71 | 72 | : null 73 | } 74 | 75 | 76 | Deaths: {data[name]['deceased']} 77 | {data[name]['delta']['deceased'] > 0 78 | ? 79 | 80 | {' '}[ {data[name]['delta']['deceased']}] 81 | 82 | : null 83 | } 84 | 85 | {/* 86 | 93 | 94 | */} 95 | 96 | 97 | <> 98 | {/* 99 | expandedRows.includes(name) ? 100 | 101 | 106 | : null 107 | */} 108 | 109 | 110 | )} 111 | 112 |
102 |
103 | 104 |
105 |
113 | 114 | 115 | ) 116 | }; 117 | 118 | export default IndiaDistrict; -------------------------------------------------------------------------------- /src/js/IndiaState.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, { useState } from 'react'; 8 | import Table from 'react-bootstrap/Table'; 9 | import Card from 'react-bootstrap/Card'; 10 | import Button from 'react-bootstrap/Button'; 11 | 12 | import { useFetch } from './useFetch'; 13 | import { URL_INDIA_DISTRICT_DAILY } from './utils/url'; 14 | 15 | import red_up_arrow from '../../assets/images/up_red_arrow.png'; 16 | import green_up_arrow from '../../assets/images/up_green_arrow.png'; 17 | 18 | import IndiaDistrict from './IndiaDistrict'; 19 | 20 | const IndiaState = props => { 21 | const stateData = props.data; 22 | const [expandedRows, setExpandedRows] = useState([]); 23 | const [districtData, loadingDistrictData] = useFetch('https://api.covid19india.org/state_district_wise.json'); 24 | // const [districtTrend, loadingDistrictTrend] = useFetch(URL_INDIA_DISTRICT_DAILY); 25 | const [expandState, setExpandState] = useState({}); 26 | 27 | const sortedStateData = stateData.sort((a,b) => b.deltaconfirmed - a.deltaconfirmed); 28 | 29 | const handleEpandRow = (event, state) => { 30 | const currentExpandedRows = expandedRows; 31 | const isRowCurrentlyExpanded = currentExpandedRows.includes(state); 32 | 33 | let tempState = {}; 34 | if (isRowCurrentlyExpanded) { 35 | let obj = {}; 36 | obj[state] = false; 37 | tempState = Object.assign({}, obj); 38 | 39 | } else { 40 | let obj = {}; 41 | obj[state] = true; 42 | tempState = Object.assign({}, obj); 43 | } 44 | 45 | setExpandState(tempState) 46 | 47 | const newExpandedRows = isRowCurrentlyExpanded ? 48 | currentExpandedRows.filter(st => st !== state) : 49 | currentExpandedRows.concat(state); 50 | 51 | setExpandedRows(newExpandedRows); 52 | } 53 | 54 | return ( 55 |
56 | 57 | 58 | States and UTs({sortedStateData.length}) 59 | 60 | State wise break-up of COVID-19 Outbreak 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {sortedStateData.map((data) => 74 | <> 75 | 76 | 88 | 101 | 106 | 119 | 131 | 132 | <> 133 | { 134 | !loadingDistrictData && expandedRows.includes(data.state) ? 135 | 136 | 144 | : null 145 | } 146 | 147 | 148 | 149 | )} 150 | 151 |
StateConfirmedActiveRecoveredDeaths
77 | {expandState[data.state] ? 👇 : 👉 } 78 | 84 | { data.lastupdatedtime && 85 | (Updated at: {data.lastupdatedtime}) 86 | } 87 | 89 |
90 | {data.confirmed}{' '} 91 | { 92 | data['deltaconfirmed'] > 0 ? 93 | 94 | [ 95 | {data['deltaconfirmed']}] 96 | : null 97 | } 98 | 99 |
100 |
102 |
103 | {data.active} 104 |
105 |
107 |
108 | {data.recovered}{' '} 109 | { 110 | data['deltarecovered'] > 0 ? 111 | 112 | [ 113 | {data['deltarecovered']}] 114 | : null 115 | } 116 | 117 |
118 |
120 |
121 | {data.deaths}{' '} 122 | { 123 | data['deltadeaths'] > 0 ? 124 | 125 | [ 126 | {data['deltadeaths']}] 127 | : null 128 | } 129 |
130 |
137 |
138 | 141 |
142 | 143 |
152 |
153 |
154 |
155 | ) 156 | }; 157 | 158 | export default IndiaState; -------------------------------------------------------------------------------- /src/js/IndiaStateCharts.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | 9 | import Container from 'react-bootstrap/Container'; 10 | import Row from 'react-bootstrap/Row'; 11 | import Col from 'react-bootstrap/Col'; 12 | 13 | import StateIndiaRecoveryProgress from './covid-all/StateIndiaRecoveryProgress'; 14 | import StateIndiaMostRadialSpreads from './covid-all/StateIndiaMostRadialSpreads'; 15 | 16 | const IndiaStateCharts = props => { 17 | 18 | const stateData = props.data; 19 | 20 | let stateDataWithPerctRecovered = stateData.map(elem => { 21 | elem['perctRecoverd'] = Math.round((elem['recovered'] * 100) / elem['confirmed']); 22 | elem['perctDeaths'] = Math.round((elem['deaths'] * 100) / elem['confirmed']); 23 | elem['perctActive'] = Math.round((elem['active'] * 100) / elem['confirmed']); 24 | return elem; 25 | }); 26 | const sortedMostRecoveredPerct = stateDataWithPerctRecovered.sort((a, b) => b.active - a.active); 27 | const indiaTotalData = props.indiaTotalData; 28 | 29 | 30 | 31 | // console.log('indiaTotalData', indiaTotalData); 32 | 33 | return ( 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | ) 50 | }; 51 | 52 | export default IndiaStateCharts; -------------------------------------------------------------------------------- /src/js/Information.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import Container from 'react-bootstrap/Container'; 9 | import Row from 'react-bootstrap/Row'; 10 | import Col from 'react-bootstrap/Col'; 11 | 12 | import covid_image from '../../assets/images/covid.png'; 13 | 14 | const Information = () => { 15 | return ( 16 |
17 | 18 | 19 | 20 |

21 | {covid_image} 28 | COVID-19 Information 29 |

30 | 31 |
32 |
33 | 34 | 35 | 36 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |

👉 Coronavirus & COVID-19

63 |

64 | Coronaviruses are a large family of viruses which may cause illness in animals or humans. In humans, 65 | several coronaviruses are known to cause respiratory infections ranging from the common cold to 66 | more severe diseases such as Middle East Respiratory Syndrome (MERS) and Severe Acute Respiratory 67 | Syndrome (SARS). The most recently discovered coronavirus causes coronavirus disease COVID-19. 68 |

69 |

70 | COVID-19 is the infectious disease caused by the most recently discovered coronavirus. This new virus 71 | and disease were unknown before the outbreak began in Wuhan, China, in December 2019. 72 |

73 | 74 |
75 | 76 | 77 |

👉 Difference with SARS-COV-2

78 |

79 | The virus that causes COVID-19 and the one that caused the outbreak of Severe Acute Respiratory Syndrome (SARS) in 2003 are related to each other genetically, but the diseases they cause are quite different. 80 |

81 |

82 | SARS was more deadly but much less infectious than COVID-19. There have been no outbreaks of SARS anywhere in the world since 2003. 83 |

84 | 85 |
86 | 87 | 88 |

👉 Symptoms

89 |

90 | The most common symptoms of COVID-19 are fever, tiredness, and dry cough. 91 |

92 |

93 | Some patients may have aches and pains, nasal congestion, runny nose, sore throat or diarrhoea. These symptoms are usually mild and begin gradually. Some people become infected but don’t develop any symptoms and don't feel unwell. Most people (about 80%) recover from the disease without needing special treatment. Around 1 out of every 6 people who gets COVID-19 becomes seriously ill and develops difficulty breathing. Older people, and those with underlying medical problems like high blood pressure, heart problems or diabetes, are more likely to develop serious illness.
94 | People with fever, cough and difficulty breathing should seek medical attention. 95 |

96 | 97 |
98 | 99 | 100 |

👉 Spreading

101 |

102 | People can catch COVID-19 from others who have the virus. The disease can spread from person to person through small droplets from the nose or mouth which are spread when a person with COVID-19 coughs or exhales. These droplets land on objects and surfaces around the person. Other people then catch COVID-19 by touching these objects or surfaces, then touching their eyes, nose or mouth. 103 |

104 |

105 | People can also catch COVID-19 if they breathe in droplets from a person with COVID-19 who coughs out or exhales droplets. This is why it is important to stay more than 1 meter (3 feet) away from a person who is sick. 106 |

107 | 108 |
109 | 110 | 111 |

👉 Risk

112 |

113 | The risk depends on where you are - and more specifically, whether there is a COVID-19 outbreak unfolding there. 114 |

115 |

116 | There are several places around the world (cities or areas) where the disease is spreading. For people living in, or visiting, these areas the risk of catching COVID-19 is higher. Governments and health authorities are taking vigorous action every time a new case of COVID-19 is identified. Be sure to comply with any local restrictions on travel, movement or large gatherings. Cooperating with disease control efforts will reduce your risk of catching or spreading COVID-19. 117 |

118 |

119 | COVID-19 outbreaks can be contained and transmission stopped, as has been shown in China and some other countries. Unfortunately, new outbreaks can emerge rapidly. It’s important to be aware of the situation where you are or intend to go. 120 |

121 | 122 |
123 | 124 | 125 |

👉 Protection

126 |

127 | Many countries around the world have seen cases of COVID-19 and several have seen outbreaks. Authorities in China and some other countries have succeeded in slowing or stopping their outbreaks. However, the situation is unpredictable so check regularly for the latest and authentic news. 128 |

129 |

130 | You can reduce your chances of being infected or spreading COVID-19 by taking some simple precautions: 131 |

    132 |
  • 133 | Regularly and thoroughly clean your hands with an alcohol-based hand rub or wash them with soap and water. Washing your hands with soap and water or using alcohol-based hand rub kills viruses that may be on your hands. 134 |
  • 135 |
  • 136 | Maintain at least 1 metre (3 feet) distance between yourself and anyone who is coughing or sneezing. When someone coughs or sneezes, they spray small liquid droplets from their nose or mouth which may contain virus. If you are too close, you can breathe in the droplets, including the COVID-19 virus if the person coughing has the disease. 137 |
  • 138 |
  • 139 | Avoid touching eyes, nose and mouth. Hands touch many surfaces and can pick up viruses. Once contaminated, hands can transfer the virus to your eyes, nose or mouth. From there, the virus can enter your body and can make you sick. 140 |
  • 141 |
  • 142 | Make sure you, and the people around you, follow good respiratory hygiene. This means covering your mouth and nose with your bent elbow or tissue when you cough or sneeze. Then dispose of the used tissue immediately. Droplets spread virus. By following good respiratory hygiene, you protect the people around you from viruses such as cold, flu and COVID-19. 143 |
  • 144 |
  • 145 | Stay home if you feel unwell. If you have a fever, cough and difficulty breathing, seek medical attention and call in advance. Follow the directions of your local health authority. National and local authorities will have the most up to date information on the situation in your area. Calling in advance will allow your health care provider to quickly direct you to the right health facility. This will also protect you and help prevent spread of viruses and other infections. 146 |
  • 147 |
  • 148 | Keep up to date on the latest COVID-19 hotspots (cities or local areas where COVID-19 is spreading widely). If possible, avoid traveling to places – especially if you are an older person or have diabetes, heart or lung disease. You have a higher chance of catching COVID-19 in one of these areas. 149 |
  • 150 |
151 |

152 | 153 |
154 |
155 |
156 | ) 157 | }; 158 | 159 | export default Information; -------------------------------------------------------------------------------- /src/js/News.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import Container from 'react-bootstrap/Container'; 9 | import Row from 'react-bootstrap/Row'; 10 | import Col from 'react-bootstrap/Col'; 11 | import Card from 'react-bootstrap/Card' 12 | import CardColumns from 'react-bootstrap/CardColumns'; 13 | 14 | import covid_image from '../../assets/images/covid.png'; 15 | 16 | import {useFetch} from "./useFetch"; 17 | import Loader from "react-loader-spinner"; 18 | 19 | const Information = () => { 20 | let data = []; 21 | const [topHeadlines, loadingTopHeadlines] = useFetch("https://saurav.tech/NewsAPI/top-headlines/category/health/in.json") 22 | 23 | if (!loadingTopHeadlines) { 24 | data = topHeadlines.articles 25 | } 26 | return ( 27 |
28 | { 29 | loadingTopHeadlines ? 30 | : 36 |
37 | 38 | 39 | 40 |

41 | {covid_image} 48 | COVID-19 News 49 |

50 | 51 |
52 |
53 | 54 | {data.map((info, index) => 55 | 56 | 57 | 58 | 59 | {info.title} 60 | 61 | 62 | {info.description} 63 | 64 | Read More.. 65 | 66 | 67 | )} 68 | 69 |
70 | } 71 |
72 | ) 73 | }; 74 | 75 | export default Information; 76 | -------------------------------------------------------------------------------- /src/js/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | 9 | const NotFoundPage = props => { 10 | return( 11 |

404 No Page Found

12 | ) 13 | }; 14 | 15 | export default NotFoundPage; -------------------------------------------------------------------------------- /src/js/Notification.js: -------------------------------------------------------------------------------- 1 | 2 | import React, { useState, useEffect, useRef } from 'react'; 3 | import { useFetch } from './useFetch'; 4 | 5 | import Overlay from 'react-bootstrap/Overlay'; 6 | import Popover from 'react-bootstrap/Popover'; 7 | import Button from 'react-bootstrap/Button'; 8 | 9 | import moment from 'moment'; 10 | 11 | import {reactLocalStorage} from 'reactjs-localstorage'; 12 | 13 | const Notification = () => { 14 | const [data, loading] = useFetch('https://api.covid19india.org/updatelog/log.json'); 15 | const [showCount, setShowCount] = useState(false); 16 | const [messageCount, setMessageCount] = useState(0); 17 | const [show, setShow] = useState(false); 18 | const [target, setTarget] = useState(null); 19 | const [raedIndex, setReadIndex] = useState(0); 20 | const ref = useRef(null); 21 | 22 | useEffect(() => { 23 | if (!loading) { 24 | data.sort((a,b) => b.timestamp - a.timestamp); 25 | 26 | // We read if any last read item id is in the local storage 27 | let readItemLs = reactLocalStorage.getObject('notification_last_read_item_id'); 28 | let readMsgId = Object.keys(readItemLs).length > 0 ? readItemLs['id'] : ''; 29 | 30 | // if the id found, we check what is the index of that message in the array and query it. If not found, 31 | // nothing has been read. Hence count should be same as all the mmesage count. 32 | let readIndex = (readMsgId === '') ? data.length : data.findIndex(elem => elem.timestamp === readMsgId); 33 | 34 | // if the id is not found, it all flushed out and start again 35 | readIndex === -1 ? readIndex = 50 : readIndex; 36 | 37 | setReadIndex(readIndex); 38 | 39 | // If there are messages and readIndex is pointing to at least one message, we will show the count bubble. 40 | (data.length && readIndex) > 0 ? setShowCount(true) : setShowCount(false); 41 | setMessageCount(readIndex); 42 | 43 | } 44 | },[loading]); 45 | 46 | const handleClick = (event) => { 47 | setShow(!show); 48 | setTarget(event.target); 49 | } 50 | 51 | const getDayDiff = timestamp => { 52 | var a = moment(); 53 | var b = moment(timestamp * 1000); 54 | let diff = a.diff(b, 'days'); 55 | if (diff === 0) { 56 | diff = a.diff(b, 'hour'); 57 | 58 | if (diff === 0) { 59 | diff = a.diff(b, 'minute'); 60 | return `${diff} minute(s) before` 61 | } else { 62 | return `${diff} hour(s) before`; 63 | } 64 | } else { 65 | return `${diff} day(s) before`; 66 | } 67 | } 68 | 69 | const getContent = message => { 70 | if (message.indexOf('\n')) { 71 | let splitted = message.split('\n'); 72 | let ret = '
    '; 73 | for (let i = 0; i' + splitted[i] + ''; 76 | } 77 | } 78 | ret = ret + '
'; 79 | return { __html: ret }; 80 | } 81 | return `${message}`; 82 | } 83 | 84 | const hide = () => { 85 | setShow(false); 86 | } 87 | 88 | const markAsRead = () => { 89 | setShowCount(false); 90 | reactLocalStorage.setObject('notification_last_read_item_id', {'id': data[0].timestamp}); 91 | setReadIndex(0); 92 | } 93 | 94 | return ( 95 | <> 96 |
97 |
handleClick(event)}> 100 | 101 |
102 |
103 | 104 |
105 | 114 | 115 | Breaking Alerts! 116 | { !loading ? 117 | 118 | {showCount &&
119 | 120 |
} 121 |
    122 | { 123 | data.map((message, index) => 124 |
  • 127 |
    {getDayDiff(message.timestamp)}
    128 |
    129 |
  • 130 | ) 131 | } 132 |
133 |
: null 134 | } 135 |
136 |
137 |
138 | 139 | ) 140 | }; 141 | 142 | export default Notification; -------------------------------------------------------------------------------- /src/js/World.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, { useState, useEffect } from "react"; 8 | 9 | import { useSelector } from 'react-redux'; 10 | 11 | import Container from 'react-bootstrap/Container'; 12 | import Row from 'react-bootstrap/Row'; 13 | import Col from 'react-bootstrap/Col'; 14 | import FormControl from 'react-bootstrap/FormControl'; 15 | 16 | import { AgGridReact } from 'ag-grid-react'; 17 | 18 | import { useFetch } from './useFetch'; 19 | 20 | import OverAllWidget from './covid-all/OverAllWidget'; 21 | import TopNDeathWidget from './covid-all/TopNDeathWidget'; 22 | import TopNRecoveredWidget from './covid-all/TopNRecoveredWidget'; 23 | import TopNTodayDeath from './covid-all/TopNTodayDeath'; 24 | import CountryCasesWidget from './covid-all/CountryCasesWidget'; 25 | import CompareWidget from './covid-all/CompareWidget'; 26 | import CountryTestCase from './covid-all/CountryTestCase'; 27 | 28 | import world from '../../assets/images/world.png'; 29 | 30 | const World = props => { 31 | const covid19Data = useSelector(state => state.covid19); 32 | let data = covid19Data.filter(elem => { 33 | return elem['country'] !== 'World'; 34 | }) 35 | const [allData, allDataLoading] = useFetch( 36 | "https://corona.lmao.ninja/v2/all" 37 | ); 38 | const [filtered, setFiltered] = useState([]); 39 | const columnDefs = [ 40 | { headerName: "Country", field: "country", sortable: true, filter: true }, 41 | { headerName: "Total Cases", field: "cases", sortable: true, filter: true }, 42 | { headerName: "Cases Today", field: "todayCases", sortable: true, filter: true }, 43 | { headerName: "Deaths", field: "deaths", sortable: true, filter: true }, 44 | { headerName: "Deaths Today", field: "todayDeaths", sortable: true, filter: true }, 45 | { headerName: "Recovered", field: "recovered", sortable: true, filter: true }, 46 | { headerName: "Active Cases", field: "active", sortable: true, filter: true }, 47 | { headerName: "Critical", field: "critical", sortable: true, filter: true }, 48 | { headerName: "Cases Per One Million", field: "casesPerOneMillion", sortable: true }, 49 | 50 | ]; 51 | 52 | useEffect(() => { 53 | setFiltered(data); 54 | }, []); 55 | 56 | const handleFind = event => { 57 | event.preventDefault(); 58 | let filtered = data.filter(elem => { 59 | return elem.country.toLowerCase().includes(event.target.value.toLowerCase()); 60 | 61 | }); 62 | setFiltered(filtered); 63 | } 64 | 65 | return ( 66 |
67 | 68 | 69 | 70 |

71 | World 77 | World 78 |

79 | 80 |
81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
113 | 114 | {/* 115 |
116 |

Country Data

117 |
118 | handleFind(event)} /> 123 | 124 |
125 | 126 |
135 | 138 | 139 |
140 |
141 | */ 142 | } 143 | 144 |
145 | ) 146 | }; 147 | 148 | export default World; -------------------------------------------------------------------------------- /src/js/actions/covidAction.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | export const registerCovid19Data = covidData => { 8 | return { 9 | type: 'REGISTER_COVID_19_DATA', 10 | payload: covidData 11 | } 12 | }; 13 | 14 | export const registerCovidTSData = covidTSData => { 15 | return { 16 | type: 'REGISTER_COVID_TS_DATA', 17 | payload: covidTSData 18 | } 19 | }; -------------------------------------------------------------------------------- /src/js/actions/timeseriesAction.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import store from '../store'; 8 | 9 | export const fetch_timeseries = () => { 10 | return { 11 | type: 'FETCH_TIMESERIES' 12 | }; 13 | }; 14 | 15 | export const recieve_timeseries = timeseries => { 16 | return { 17 | type: 'FETCHED_TIMESERIES', 18 | data: timeseries 19 | }; 20 | }; 21 | 22 | export const recieve_error = () => { 23 | return { 24 | type: 'RECIEVED_ERROR' 25 | }; 26 | }; 27 | 28 | export const thunk_timeseries_action_creator = () => { 29 | store.dispatch(fetch_timeseries()); 30 | return function ( dispatch, getState ) { 31 | return fetch ( 'https://pomber.github.io/covid19/timeseries.json' ) 32 | .then ( data => data.json() ) 33 | .then ( data => { 34 | dispatch ( recieve_timeseries(data) ); 35 | }) 36 | .catch ( err => dispatch ( recieve_error() )); 37 | }; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /src/js/charts/RadarCovidChart.js: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | import { 4 | Radar, 5 | RadarChart, 6 | PolarGrid, 7 | Legend, 8 | PolarAngleAxis, 9 | PolarRadiusAxis, 10 | Tooltip, 11 | ResponsiveContainer 12 | } from 'recharts'; 13 | 14 | import COLOR_CODES from '../utils/color_codes'; 15 | 16 | const RadarCovidChart = props => { 17 | 18 | const data = props.radarData; 19 | const key = props.chartKey; 20 | 21 | let color = COLOR_CODES.RANDOM.BLACK; 22 | let name = 'None'; 23 | if (key === 'deaths') { 24 | color = COLOR_CODES.CATEGORIES.DEATHS; 25 | name = 'Deaths'; 26 | } else if (key === 'active') { 27 | color = COLOR_CODES.CATEGORIES.ACTIVE; 28 | name = 'Active'; 29 | } else if (key === 'recovered') { 30 | color = COLOR_CODES.CATEGORIES.RECOVERED; 31 | name = 'Recovered'; 32 | } else if (key === 'confirmed') { 33 | color = COLOR_CODES.CATEGORIES.CONFIRMED; 34 | name = 'Confirmed'; 35 | } 36 | 37 | let sliced = data.slice(0, props.top_n); 38 | console.log('RadarCovidChart', sliced, key); 39 | 40 | return( 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ) 51 | }; 52 | 53 | export default RadarCovidChart; -------------------------------------------------------------------------------- /src/js/covid-all/CompareWidget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, { useState } from 'react'; 8 | import { 9 | ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, 10 | } from 'recharts'; 11 | import Loader from 'react-loader-spinner'; 12 | import Card from 'react-bootstrap/Card'; 13 | import {reactLocalStorage} from 'reactjs-localstorage'; 14 | 15 | import FetchTimeSeries from '../time-series/FetchTimeSeries'; 16 | import { useFetch } from '../useFetch'; 17 | import CountrySelector from '../CountrySelector'; 18 | 19 | let randomColor = require('randomcolor'); 20 | const COLOR_ARRAY = randomColor({ 21 | count: 25, 22 | luminosity: 'bright', 23 | hue: 'random' 24 | }); 25 | 26 | 27 | const CompareWidget = props => { 28 | // import the script 29 | 30 | let defaultCountries = { 31 | 'India': true, 32 | 'USA': true, 33 | 'Brazil': true, 34 | 'Italy': true, 35 | 'France': true, 36 | 'Germany': true 37 | }; 38 | let storedCountries = reactLocalStorage.getObject('compare_widget_country_selected'); 39 | if (storedCountries && Object.keys(storedCountries).length > 0) { 40 | defaultCountries = storedCountries; 41 | } 42 | const [data, loading] = useFetch('https://pomber.github.io/covid19/timeseries.json'); 43 | const [selectedCountries, setSelectedCountries] = useState(defaultCountries); 44 | 45 | const getCountryResolvedName = input => { 46 | if (input === 'USA') { 47 | return 'US'; 48 | } if (input === 'UK') { 49 | return 'United Kingdom' 50 | } if (input === 'S. Korea') { 51 | return 'Korea, South'; 52 | } else { 53 | return input; 54 | } 55 | }; 56 | 57 | const getCountriesToCompare = () => { 58 | let countries = Object.keys(selectedCountries).filter(elem => { 59 | return selectedCountries[elem] === true; 60 | }); 61 | 62 | return countries; 63 | } 64 | 65 | const getCountryFirstIndex = countryData => { 66 | let i = 0; 67 | if (countryData) { 68 | for(; i < countryData.length; i++) { 69 | if (countryData[i].confirmed > 0) { 70 | break; 71 | } 72 | } 73 | } 74 | return i; 75 | } 76 | 77 | const getWeekArray = (country, timeseries) => { 78 | let firstIndex = getCountryFirstIndex(timeseries); 79 | let wk = 1; 80 | let arr = []; 81 | for (let i = firstIndex; i < timeseries.length; i = i + 7) { 82 | let obj = {}; 83 | obj['week'] = `WK ${wk}`; 84 | obj[country] = timeseries[i].confirmed; 85 | obj[`${country}-week-date`] = timeseries[i].date; 86 | arr.push(obj); 87 | wk++; 88 | } 89 | if ((((arr.length - 1) * 7) + firstIndex) < timeseries.length - 1) { 90 | let obj = {}; 91 | obj['week'] = `WK ${wk}`; 92 | obj[country] = timeseries[timeseries.length - 1].confirmed; 93 | obj[`${country}-week-date`] = timeseries[timeseries.length - 1].date; 94 | arr.push(obj); 95 | } 96 | return arr; 97 | } 98 | 99 | const getData = () => { 100 | let accumulator = []; 101 | getCountriesToCompare().forEach(country => { 102 | let resolvedName = getCountryResolvedName(country); 103 | let timeseries = data[resolvedName]; 104 | if (timeseries) { 105 | let arr = getWeekArray(country, timeseries); 106 | accumulator.push(arr); 107 | } 108 | }); 109 | let concated = []; 110 | accumulator.forEach(item => { 111 | concated = concated.concat(item); 112 | }) 113 | 114 | let joined = concated.reduce((acc, x) => { 115 | acc[x.week] = Object.assign(acc[x.week] || {}, x); 116 | return acc; 117 | }, {}); 118 | 119 | return Object.values(joined); 120 | } 121 | 122 | let chartData = []; 123 | if (!loading) { 124 | chartData = getData(); 125 | } 126 | 127 | const CustomTooltip = ({ active, payload, label }) => { 128 | if (active) { 129 | return ( 130 |
131 |
Comparison at {`${payload[0].payload.week}`}
132 |
133 | { 134 | getCountriesToCompare().map((entry, index) => 135 | payload[0].payload[entry] ? 136 |

137 | 138 | {entry}: {payload[0].payload[entry]} {' '} 139 | (Computed on {payload[0].payload[`${entry}-week-date`]}) 140 | 141 |

: null 142 | ) 143 | } 144 |
145 | ); 146 | } 147 | 148 | return null; 149 | }; 150 | 151 | const getCountryFlagName = input => { 152 | if (input === 'US') { 153 | return 'USA'; 154 | } if (input === 'United Kingdom') { 155 | return 'UK' 156 | } if (input === 'Korea, South') { 157 | return 'S. Korea'; 158 | } else { 159 | return input; 160 | } 161 | }; 162 | 163 | 164 | const updateCountries = countries => { 165 | setSelectedCountries(countries); 166 | reactLocalStorage.setObject('compare_widget_country_selected', countries); 167 | } 168 | 169 | return( 170 |
171 | { loading ? 172 | : 178 | 179 | 180 | 181 | 182 | Compare Countries over the Weeks 183 | { 184 | chartData.length > 0 ? 185 | 188 | : null 189 | } 190 | 191 | { 192 | chartData.length > 0 ? 193 | 194 | Countries({getCountriesToCompare().length}) : 195 | { 196 | getCountriesToCompare().map((entry, index) => 197 | ) 198 | } 199 | 200 | : null 201 | } 202 | { 203 | chartData.length > 0 ? 204 | 205 | 207 | 208 | 209 | 210 | } /> 211 | 212 | { 213 | getCountriesToCompare().map((entry, index) => 214 | ) 215 | } 216 | 217 | : 218 |

219 | Select One or more countries to compare 220 | 223 |

224 | } 225 |
226 |
227 | } 228 |
229 | ) 230 | }; 231 | 232 | export default CompareWidget; -------------------------------------------------------------------------------- /src/js/covid-all/CountryCasesWidget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import { 9 | ResponsiveContainer, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, 10 | } from 'recharts'; 11 | import Card from 'react-bootstrap/Card'; 12 | 13 | import COLOR_CODES from '../utils/color_codes'; 14 | 15 | const CountryCasesWidget = props => { 16 | const data = props.data; 17 | const TOP_N = 15; 18 | 19 | let refinedData = []; 20 | let sortedData = data.sort((a, b) => b.cases - a.cases); 21 | let cloned = JSON.parse(JSON.stringify(sortedData)); 22 | let topNData = cloned.splice(0, TOP_N); 23 | 24 | topNData.forEach(element => { 25 | let obj = {}; 26 | obj['Country'] = element['country']; 27 | obj['Cases'] = element['cases']; 28 | obj['Recovered'] = element['recovered']; 29 | obj['Deaths'] = element['deaths']; 30 | refinedData.push(obj); 31 | }); 32 | 33 | 34 | return( 35 |
36 | 37 | 38 | Major Country Spreads(Total Confirmed Cases) 39 | Number of Countries: {TOP_N} 40 |
41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 |
53 |
54 |
55 | ) 56 | }; 57 | 58 | export default CountryCasesWidget; -------------------------------------------------------------------------------- /src/js/covid-all/CountryTestCase.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Card from 'react-bootstrap/Card'; 3 | import { useSelector } from 'react-redux'; 4 | import { 5 | ResponsiveContainer, 6 | BarChart, 7 | Bar, 8 | Cell, 9 | XAxis, 10 | YAxis, 11 | CartesianGrid, 12 | Tooltip, 13 | Label, 14 | LabelList 15 | } from 'recharts'; 16 | import {reactLocalStorage} from 'reactjs-localstorage'; 17 | import CurrencyFormat from 'react-currency-format'; 18 | 19 | 20 | let randomColor = require('randomcolor'); 21 | 22 | const CountryTestCase = () => { 23 | 24 | const countryNameFromStorage = reactLocalStorage.getObject('country_selection'); 25 | 26 | const MY_COUNTRY = Object.keys(countryNameFromStorage).length > 0 ? 27 | countryNameFromStorage : 28 | 'India'; 29 | 30 | const SUCCESS_COLOR_SHADES = randomColor({ 31 | count: 11, 32 | luminosity: 'bright', 33 | hue: 'random' 34 | }); 35 | 36 | const covid19Data = useSelector(state => state.covid19); 37 | 38 | let countryData = covid19Data.map(({ country, tests, cases, perct }) => ({ country, tests, cases })).filter(elem => { 39 | return (elem.tests > 0 || elem.country === 'World') 40 | }); 41 | countryData.map(elem => { 42 | let calc = elem['cases'] * 100 / elem['tests']; 43 | elem['perct'] = calc.toFixed(2); 44 | return elem; 45 | }); 46 | 47 | let sortedData = countryData.sort((a, b) => b.cases - a.cases); 48 | let cloned = JSON.parse(JSON.stringify(sortedData)); 49 | let topNData = cloned.splice(0, 9); 50 | 51 | const foundMyCountry = topNData.filter(elem => { 52 | return elem.country === MY_COUNTRY; 53 | }); 54 | 55 | if (foundMyCountry.length === 0) { 56 | topNData.push(countryData.filter(elem => { 57 | return elem.country === MY_COUNTRY 58 | })[0]); 59 | } 60 | 61 | let refinedData = []; 62 | topNData.forEach(element => { 63 | let obj = {}; 64 | obj['country'] = element['country']; 65 | obj['% Positive'] = element['perct']; 66 | obj['cases'] = element['cases']; 67 | obj['tests'] = element['tests']; 68 | refinedData.push(obj); 69 | }); 70 | 71 | const maxDomain = Math.round(topNData.sort((a, b) => b.perct - a.perct)[0]['perct']) + 20 72 | 73 | const CustomTooltip = ({ active, payload, label }) => { 74 | if (active) { 75 | return ( 76 |
77 |

{`${payload[0].payload.country}`}

78 |
79 | 84 |
85 | {`Total Tests Done: ${value}`} 86 |
} 87 | /> 88 | 89 | 94 |
95 | {`Total Cases: ${value}`} 96 |
} 97 | /> 98 | 99 | 104 |
105 | {`Cases vs Tests (%Positive): ${value}%`} 106 |
} 107 | /> 108 |
109 |
110 | ); 111 | } 112 | 113 | return null; 114 | }; 115 | 116 | const renderCustomizedLabel = (props) => { 117 | const { x, y, width, height, value } = props; 118 | const radius = 23; 119 | 120 | return ( 121 | 122 | 123 | 124 | {value}% 125 | 126 | 127 | ); 128 | }; 129 | 130 | return ( 131 |
132 | 133 | 134 | Country Tests vs Positive 135 | Percentage of Postive Cases Compared to the Test done. 136 |
137 | 138 | 144 | 145 | 146 | 148 | 149 | } /> 150 | 151 | 152 | { 153 | refinedData.map((entry, index) => ( 154 | 155 | )) 156 | } 157 | 158 | 159 | 160 | 161 |
162 |
163 |
164 |
165 | ) 166 | }; 167 | 168 | export default CountryTestCase; -------------------------------------------------------------------------------- /src/js/covid-all/OverAllWidget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | import Badge from 'react-bootstrap/Badge'; 9 | import Card from 'react-bootstrap/Card'; 10 | import { 11 | ResponsiveContainer, PieChart, Pie, Legend, Tooltip, Cell 12 | } from 'recharts'; 13 | 14 | import Moment from 'react-moment'; 15 | import Loader from 'react-loader-spinner'; 16 | import CurrencyFormat from 'react-currency-format'; 17 | 18 | const WorldData = props => { 19 | const loading = props.loading; 20 | const data = props.data; 21 | 22 | let refinedData = []; 23 | if (!loading) { 24 | let keys = Object.keys(data); 25 | keys.forEach((elem) => { 26 | if (elem === 'deaths' || elem === 'recovered' || elem === 'active') { 27 | let obj = {}; 28 | obj['name'] = elem; 29 | obj['value'] = data[elem]; 30 | refinedData.push(obj); 31 | } 32 | }); 33 | } 34 | const COLORS = ['#DC3545', '#28A745', '#FFC107']; 35 | return ( 36 |
37 | 38 | 39 | 40 | Total Cases: as on {data.updated} 41 | 42 | Recovery, Deaths and Still Infected 43 |
44 | {loading ? 45 | 51 | : 52 |
53 | 54 | 55 | 64 | { 65 | refinedData.map((entry, index) => ) 66 | } 67 | 68 | 69 | 70 | 71 |
72 | 73 | {`Recovered - ${Math.round((data.recovered * 100) / data.cases)}%`} 74 | 75 | 76 | {`Active - ${Math.round(((data.active) * 100) / data.cases)}%`} 77 | 78 | 79 | {`Deaths - ${Math.round((data.deaths * 100) / data.cases)}%`} 80 | 81 |
82 |
83 | } 84 |
85 |
86 |
87 | 88 | 89 |
90 | ) 91 | }; 92 | 93 | export default WorldData; -------------------------------------------------------------------------------- /src/js/covid-all/StateIndiaMostConfirmed.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import Card from 'react-bootstrap/Card'; 9 | import { 10 | ResponsiveContainer, ScatterChart, Scatter, XAxis, YAxis, ZAxis, CartesianGrid, Tooltip 11 | } from 'recharts'; 12 | 13 | import INDIA_STATE_CODES from '../utils/india_state_codes'; 14 | 15 | const StateIndiaMostConfirmed = props => { 16 | const MIN_CASES_TO_SHOW = 200; 17 | const data = props.data; 18 | 19 | let filteredData = data.filter(elem => { 20 | return elem.active > MIN_CASES_TO_SHOW; 21 | }); 22 | 23 | let refinedData = []; 24 | filteredData.forEach(element => { 25 | let obj = {}; 26 | obj['State'] = element['state']; 27 | obj['State Code'] = INDIA_STATE_CODES[element['state']]; 28 | obj['Confirmed'] = element['confirmed']; 29 | obj['Active'] = element['active']; 30 | obj['Deaths'] = element['deaths']; 31 | obj['Recovered'] = element['recovered']; 32 | obj['New Case(Today)'] = element['deltaconfirmed']; 33 | obj['New Deaths(Today)'] = element['deltadeaths']; 34 | obj['New Recovery(Today)'] = element['deltarecovered']; 35 | refinedData.push(obj); 36 | }); 37 | 38 | const parseDomain = () => { 39 | return [ 40 | 0, 41 | Math.max.apply(null, [ 42 | ...refinedData.map(entry => entry.Active) 43 | ]) 44 | ]; 45 | }; 46 | 47 | let domain = parseDomain(); 48 | const range = [1, domain[1]]; 49 | domain[1] = domain[1] * 2; 50 | 51 | console.log(domain); 52 | console.log(range); 53 | 54 | 55 | const CustomTooltip = ({ active, payload, label }) => { 56 | if (active) { 57 | return ( 58 |
59 |

{`${payload[0].payload.State}`}: {`${payload[0].payload.Confirmed}`} Confirmed

60 |

61 | {`Active Cases: ${payload[0].payload.Active}`}
62 | {`Total Deaths: ${payload[0].payload.Deaths}`}
63 | {`Total Recovered: ${payload[0].payload.Recovered}`}
64 | Today
65 | {`New Cases: ${payload[0].payload['New Case(Today)']}`}
66 | {`New Deaths: ${payload[0].payload['New Deaths(Today)']}`}
67 | {`New Recoveries: ${payload[0].payload['New Recovery(Today)']}`} 68 |

69 |
70 | ); 71 | } 72 | 73 | return null; 74 | }; 75 | 76 | return ( 77 | 78 | 79 | State: Most Affected(Minimum {MIN_CASES_TO_SHOW} Active Cases) 80 | 81 | States with most number of Active cases. 82 | 83 | 84 | 87 | 88 | 89 | 90 | 91 | 92 | } /> 96 | 97 | 98 | 99 | 100 | ); 101 | }; 102 | 103 | export default StateIndiaMostConfirmed; -------------------------------------------------------------------------------- /src/js/covid-all/StateIndiaMostDeaths.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import Card from 'react-bootstrap/Card'; 9 | import RadarCovidChart from '../charts/RadarCovidChart'; 10 | 11 | const StateIndiaMostDeaths = props => { 12 | const data = props.data; 13 | const totalDeathIndia = props.total; 14 | console.log('StateIndiaMostDeaths data', data); 15 | const TOP_N = 10; 16 | let refinedData = []; 17 | data.forEach(element => { 18 | let obj = {}; 19 | obj['state'] = element['state']; 20 | obj['deaths'] = parseInt(element['deaths'], 10); 21 | obj['total'] = totalDeathIndia; 22 | refinedData.push(obj); 23 | }); 24 | 25 | console.log('StateIndiaMostDeaths refinedData', refinedData); 26 | 27 | return ( 28 | 29 | 30 | State: Most Death Cases Spreads 31 | 32 | Top {TOP_N} states with Most Death Cases Spreads 33 | 34 | 35 | 36 | 37 | ); 38 | }; 39 | 40 | export default StateIndiaMostDeaths; -------------------------------------------------------------------------------- /src/js/covid-all/StateIndiaMostRadialSpreads.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, { useState } from 'react'; 8 | import Card from 'react-bootstrap/Card'; 9 | import RadarCovidChart from '../charts/RadarCovidChart'; 10 | 11 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 12 | import Button from 'react-bootstrap/Button'; 13 | import INDIA_STATE_CODES from '../utils/india_state_codes'; 14 | 15 | const StateIndiaMostRadialSpreads = props => { 16 | const [type, setType] = useState('confirmed'); 17 | const [btnState, setBtnState] = useState({ 18 | 'confirmed': true, 19 | 'active': false, 20 | 'recovered': false, 21 | 'deaths': false 22 | }); 23 | const stateData = props.stateData; 24 | const totalActiveIndia = props.total; 25 | const TOP_N = 12; 26 | 27 | let refinedData = []; 28 | const sortedMostType = [...stateData].sort((a, b) => parseInt(b[type], 10) - parseInt(a[type], 10)); 29 | sortedMostType.forEach(element => { 30 | let obj = {}; 31 | obj['state'] = element['state']; 32 | obj[type] = parseInt(element[type], 10); 33 | obj['total'] = parseInt(totalActiveIndia[type], 10); 34 | refinedData.push(obj); 35 | }); 36 | 37 | const handleTypeClick = (type, color) => { 38 | setType(type); 39 | 40 | let tempState = Object.assign({}, { 41 | 'confirmed': false, 42 | 'active': false, 43 | 'recovered': false, 44 | 'deaths': false 45 | }); 46 | tempState[type] = 'true'; 47 | setBtnState(tempState); 48 | } 49 | 50 | console.log('StateIndiaMostActive refinedData', refinedData); 51 | 52 | return ( 53 | 54 | 55 | State: Most {type} cases spreads 56 |
57 | 58 | 64 | 70 | 76 | 82 | 83 |
84 | 85 | Top {TOP_N} states with Most {type} cases spreads 86 | 87 | 88 |
89 |
90 | ); 91 | }; 92 | 93 | export default StateIndiaMostRadialSpreads; -------------------------------------------------------------------------------- /src/js/covid-all/StateIndiaRecoveryProgress.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import Card from 'react-bootstrap/Card'; 9 | import { 10 | ResponsiveContainer, 11 | ComposedChart, 12 | BarChart, 13 | Bar, 14 | Line, 15 | Area, 16 | Cell, 17 | XAxis, 18 | YAxis, 19 | CartesianGrid, 20 | Tooltip, 21 | Legend, 22 | Label, 23 | LabelList 24 | } from 'recharts'; 25 | 26 | import INDIA_STATE_CODES from '../utils/india_state_codes'; 27 | 28 | const StateIndiaRecoveryProgress = props => { 29 | const data = props.data; 30 | 31 | let topNData = data.filter((elem) => { 32 | return elem.confirmed > 100 && elem.state != 'State Unassigned'; 33 | }); 34 | 35 | let refinedData = []; 36 | topNData.forEach(element => { 37 | let obj = {}; 38 | obj['State'] = element['state']; 39 | obj['% Recovered'] = element['perctRecoverd']; 40 | obj['% Deaths'] = element['perctDeaths']; 41 | obj['active'] = element['active']; 42 | obj['% Active'] = element['perctActive']; 43 | obj['confirmed'] = element['confirmed']; 44 | obj['recovered'] = element['recovered']; 45 | obj['deaths'] = element['deaths']; 46 | obj['State Code'] = INDIA_STATE_CODES[element['state']]; 47 | refinedData.push(obj); 48 | }); 49 | 50 | const CustomTooltip = ({ active, payload, label }) => { 51 | if (active) { 52 | return ( 53 |
54 |

55 | {payload[0].payload.State}({`Cases: ${payload[0].payload.confirmed}`}) 56 |

57 |

58 | 59 | {`Acive Cases: ${payload[0].payload.active}(${payload[0].payload['% Active']}%)`} 60 |
61 | 62 | {`Recovered Cases: ${payload[0].payload.recovered}(${payload[0].payload['% Recovered']}%)`} 63 |
64 | 65 | {`Death Cases: ${payload[0].payload.deaths}(${payload[0].payload['% Deaths']}%)`} 66 | 67 |

68 |
69 | ); 70 | } 71 | 72 | return null; 73 | }; 74 | 75 | const renderCustomizedLabel = (props) => { 76 | const { x, y, width, height, value } = props; 77 | const radius = 18; 78 | 79 | return ( 80 | 81 | 82 | 83 | {value}% 84 | 85 | 86 | ); 87 | }; 88 | 89 | return ( 90 | 91 | 92 | State: Recovery Progress(Min. 100 Cases) 93 | 94 | State with the Active, Recovery and Death percentages 95 | 96 | 97 | 101 | 102 | 103 | } /> 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | ); 116 | }; 117 | 118 | export default StateIndiaRecoveryProgress; -------------------------------------------------------------------------------- /src/js/covid-all/TopNDeathWidget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import PropTypes from 'prop-types'; 9 | import Card from 'react-bootstrap/Card'; 10 | import { 11 | ResponsiveContainer, BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, 12 | } from 'recharts'; 13 | 14 | const TopNDeathWidget = props => { 15 | const data = props.data; 16 | const TOP_N = 5; 17 | const DANGER_COLOR_SHADES = [ 18 | "rgba(255, 0, 0, 1.0)", 19 | "rgba(255, 0, 0, 0.9)", 20 | "rgba(255, 0, 0, 0.8)", 21 | "rgba(255, 0, 0, 0.7)", 22 | "rgba(255, 0, 0, 0.6)", 23 | "rgba(255, 0, 0, 0.5)", 24 | "rgba(255, 0, 0, 0.4)", 25 | "rgba(255, 0, 0, 0.5)", 26 | "rgba(255, 0, 0, 0.2)", 27 | "rgba(255, 0, 0, 0.1)" 28 | ]; 29 | 30 | let refinedData = []; 31 | 32 | let sortedData = data.sort((a, b) => b.deaths - a.deaths); 33 | let cloned = JSON.parse(JSON.stringify(sortedData)); 34 | let topNData = cloned.splice(0, TOP_N); 35 | 36 | topNData.forEach(element => { 37 | let obj = {}; 38 | obj['country'] = element['country']; 39 | obj['deaths'] = element['deaths']; 40 | refinedData.push(obj); 41 | }); 42 | 43 | const getPath = (x, y, width, height) => { 44 | return `M${x},${y + height} 45 | C${x + width / 3},${y + height} ${x + width / 2},${y + height / 3} ${x + width / 2}, ${y} 46 | C${x + width / 2},${y + height / 3} ${x + 2 * width / 3},${y + height} ${x + width}, ${y + height} 47 | Z`; 48 | }; 49 | 50 | const TriangleBar = (props) => { 51 | const { fill, x, y, width, height } = props; 52 | 53 | return ; 54 | }; 55 | 56 | TriangleBar.propTypes = { 57 | fill: PropTypes.string, 58 | x: PropTypes.number, 59 | y: PropTypes.number, 60 | width: PropTypes.number, 61 | height: PropTypes.number, 62 | }; 63 | 64 | return ( 65 |
66 | 67 | 68 | Countries with Overall Death Impact 69 | Number of Countries: {TOP_N} 70 |
71 | 72 | 75 | 76 | 77 | 78 | 79 | 80 | } label={{ position: 'top' }}> 81 | { 82 | refinedData.map((entry, index) => ( 83 | 84 | )) 85 | } 86 | 87 | 88 | 89 |
90 |
91 |
92 |
93 | ) 94 | }; 95 | 96 | export default TopNDeathWidget; -------------------------------------------------------------------------------- /src/js/covid-all/TopNRecoveredWidget.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import { 9 | ResponsiveContainer, BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, 10 | } from 'recharts'; 11 | import Card from 'react-bootstrap/Card'; 12 | 13 | const TopNRecoveredWidget = props => { 14 | const data = props.data; 15 | const TOP_N = 5; 16 | const MIN_CASES = 10000; 17 | const SUCCESS_COLOR_SHADES = [ 18 | "rgba(40, 167, 69, 1.0)", 19 | "rgba(40, 167, 69, 0.9)", 20 | "rgba(40, 167, 69, 0.8)", 21 | "rgba(40, 167, 69, 0.7)", 22 | "rgba(40, 167, 69, 0.6)", 23 | "rgba(40, 167, 69, 0.5)", 24 | "rgba(40, 167, 69, 0.4)", 25 | "rgba(40, 167, 69, 0.5)", 26 | "rgba(40, 167, 69, 0.2)", 27 | "rgba(40, 167, 69, 0.1)" 28 | ]; 29 | 30 | let refinedData = []; 31 | 32 | let coutriesWithMinCases = data.filter(elem => { 33 | return elem.cases >= MIN_CASES && elem.country !== 'Diamond Princess'; 34 | }); 35 | let mappedData = coutriesWithMinCases.map(elem => { 36 | elem['recovPerc'] = Math.round((elem['recovered'] * 100) / elem['cases']); 37 | return elem; 38 | }); 39 | let sortedData = mappedData.sort((a, b) => b.recovPerc - a.recovPerc); 40 | let cloned = JSON.parse(JSON.stringify(sortedData)); 41 | let topNData = cloned.splice(0, TOP_N); 42 | topNData.forEach(element => { 43 | let obj = {}; 44 | obj['country'] = element['country']; 45 | obj['%recovered'] = element['recovPerc']; 46 | obj['cases'] = element['cases']; 47 | obj['recovered'] = element['recovered']; 48 | refinedData.push(obj); 49 | }); 50 | 51 | const CustomTooltip = ({ active, payload, label }) => { 52 | if (active) { 53 | return ( 54 |
55 |

{`${label} : ${payload[0].value}`}% Recovered

56 |

57 | {`Recovered Cases: ${payload[0].payload.recovered}`}
58 | {`Total Cases: ${payload[0].payload.cases}`} 59 |

60 |
61 | ); 62 | } 63 | 64 | return null; 65 | }; 66 | 67 | return ( 68 |
69 | 70 | 71 | Countries Recovering Well(min. {MIN_CASES} Cases) 72 | Number of Countries: {TOP_N} 73 |
74 | 75 | 81 | 82 | 83 | 84 | }/> 85 | 86 | 87 | { 88 | refinedData.map((entry, index) => ( 89 | 90 | )) 91 | } 92 | 93 | 94 | 95 |
96 |
97 |
98 |
99 | ) 100 | }; 101 | 102 | export default TopNRecoveredWidget; -------------------------------------------------------------------------------- /src/js/covid-all/TopNTodayDeath.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import { 9 | ResponsiveContainer, BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, 10 | } from 'recharts'; 11 | import Card from 'react-bootstrap/Card'; 12 | 13 | const TopNTodayDeath = props => { 14 | const data = props.data; 15 | const TOP_N = 5; 16 | const DANGER_COLOR_SHADES = [ 17 | "rgba(255, 0, 0, 1.0)", 18 | "rgba(255, 0, 0, 0.8)", 19 | "rgba(255, 0, 0, 0.6)", 20 | "rgba(255, 0, 0, 0.4)", 21 | "rgba(255, 0, 0, 0.2)" 22 | ]; 23 | let refinedData = []; 24 | 25 | let sortedData = data.sort((a, b) => b.todayDeaths - a.todayDeaths); 26 | let cloned = JSON.parse(JSON.stringify(sortedData)); 27 | let topNData = cloned.splice(0, TOP_N); 28 | 29 | topNData.forEach(element => { 30 | let obj = {}; 31 | obj['country'] = element['country']; 32 | obj['Today Deaths'] = element['todayDeaths']; 33 | refinedData.push(obj); 34 | }); 35 | 36 | return ( 37 |
38 | 39 | 40 | Countries with maximum Deaths Today 41 | Number of Countries: {TOP_N} 42 |
43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | { 57 | refinedData.map((entry, index) => ( 58 | 59 | )) 60 | } 61 | 62 | 63 | 64 |
65 |
66 |
67 |
68 | ) 69 | }; 70 | 71 | export default TopNTodayDeath; -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | import ReactDOM from "react-dom"; 9 | import 'bootstrap/dist/css/bootstrap.min.css'; 10 | import 'ag-grid-community/dist/styles/ag-grid.css'; 11 | import 'ag-grid-community/dist/styles/ag-theme-balham.css'; 12 | import "react-loader-spinner/dist/loader/css/react-spinner-loader.css"; 13 | import '../../assets/styles/sass/styles.scss'; 14 | import '@fortawesome/fontawesome-free/js/all'; 15 | 16 | import { Provider } from 'react-redux'; 17 | import store from './store'; 18 | 19 | import App from "./App"; 20 | 21 | 22 | ReactDOM.render( 23 | 24 | 25 | , 26 | document.getElementById("app") 27 | ); -------------------------------------------------------------------------------- /src/js/reducers/covid19Reducer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | const covid19Reducer = (state = {}, action) => { 8 | switch(action.type) { 9 | case 'REGISTER_COVID_19_DATA' : 10 | state = action.payload; 11 | return state; 12 | break; 13 | default: 14 | return state; 15 | break; 16 | } 17 | }; 18 | 19 | export default covid19Reducer; -------------------------------------------------------------------------------- /src/js/reducers/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import timeseriesReducer from './timeseriesReducer'; 8 | import covid19Reducer from './covid19Reducer'; 9 | 10 | import { combineReducers } from 'redux'; 11 | 12 | const allReducers = combineReducers({ 13 | covid19: covid19Reducer, 14 | timeseries: timeseriesReducer 15 | }); 16 | 17 | export default allReducers; -------------------------------------------------------------------------------- /src/js/reducers/timeseriesReducer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | const timeseriesReducer = ( state = {}, action ) => { 8 | switch ( action.type ) { 9 | case 'REGISTER_COVID_TS_DATA': 10 | state = action.payload; 11 | return state; 12 | break; 13 | default: 14 | return state; 15 | } 16 | }; 17 | 18 | export default timeseriesReducer; -------------------------------------------------------------------------------- /src/js/store/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import store from './store'; 8 | 9 | export default store; -------------------------------------------------------------------------------- /src/js/store/store.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import { createStore } from 'redux'; 8 | 9 | import allReducers from '../reducers'; 10 | 11 | const store = createStore( allReducers, 12 | window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ); 13 | 14 | export default store; -------------------------------------------------------------------------------- /src/js/time-series/FetchTimeSeries.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | import Button from 'react-bootstrap/Button'; 9 | 10 | 11 | import COUNTRY_CODES from '../utils/country_code'; 12 | 13 | const FetchTimeSeries = props => { 14 | const country = props.country; 15 | const size = props.size ? props.size : 48; 16 | 17 | let selectedCountry = []; 18 | let image = ''; 19 | 20 | selectedCountry = COUNTRY_CODES.filter( elem => { 21 | return elem.name === country; 22 | }); 23 | if (selectedCountry.length > 0) { 24 | let countryCode = selectedCountry[0]['alpha2code']; 25 | image = {country} 26 | } 27 | 28 | const getCountryDetails = (event, country) => { 29 | event.preventDefault(); 30 | if (props.history) { 31 | props.history.push(`/country-details?name=${country}`); 32 | } 33 | } 34 | 35 | return( 36 | 37 | 48 | 49 | ); 50 | }; 51 | 52 | export default FetchTimeSeries; -------------------------------------------------------------------------------- /src/js/time-series/IndiaDistrictTrend.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend 4 | } from 'recharts'; 5 | 6 | import { useFetch } from '../useFetch'; 7 | import COLOR_CODES from '../utils/color_codes'; 8 | 9 | const IndiaDistrictTrend = props => { 10 | const districtTrendData = props.districtTrendData; 11 | console.log('IndiaDistrictTrend', districtTrendData); 12 | return ( 13 |
14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | ) 29 | }; 30 | 31 | export default IndiaDistrictTrend; -------------------------------------------------------------------------------- /src/js/time-series/TimeSeries.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from "react"; 8 | import { useFetch } from '../useFetch'; 9 | import { 10 | ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, 11 | } from 'recharts'; 12 | import Loader from 'react-loader-spinner'; 13 | import Card from 'react-bootstrap/Card'; 14 | 15 | import TimeSeriesBroken from './TimeSeriesBroken'; 16 | import TimeSeriesPercentage from './TimeSeriesPercentage'; 17 | 18 | const TimeSeries = props => { 19 | const [data, loading] = useFetch('https://pomber.github.io/covid19/timeseries.json'); 20 | const country = props.country; 21 | const indiaData = props.indiaData; 22 | 23 | const getProposedName = country => { 24 | if (country === 'S. Korea') { 25 | return 'Korea, South'; 26 | } else if (country === 'UK') { 27 | return 'United Kingdom'; 28 | } else if (country === 'USA') { 29 | return 'US'; 30 | } else { 31 | return country; 32 | } 33 | } 34 | let refinedData = []; 35 | let brokenDownData = []; 36 | let percentageData = []; 37 | 38 | if (country === 'India') { 39 | refinedData = indiaData.cases_time_series.map(elem => { 40 | if (elem.totalconfirmed !== '') { 41 | elem['confirmed'] = parseInt(elem.totalconfirmed, 10); 42 | } 43 | if (elem.totaldeceased !== '') { 44 | elem['deaths'] = parseInt(elem.totaldeceased, 10); 45 | } 46 | if (elem.totalrecovered !== '') { 47 | elem['recovered'] = parseInt(elem.totalrecovered, 10); 48 | } 49 | 50 | if (elem.totalconfirmed !== '' 51 | && elem.totaldeceased !== '' 52 | && elem.totalrecovered !== '') { 53 | elem['active'] = (elem['confirmed'] - (elem['recovered'] + elem['deaths'])); 54 | } 55 | return elem; 56 | }); 57 | for (let i = 0; i 0) { 70 | percentageObj['% Change'] = refinedData[i-1]['confirmed'] === 0 ? 0 : 71 | ((parseInt(refinedData[i]['dailyconfirmed'], 10) * 100) / refinedData[i-1]['confirmed']).toFixed(2); 72 | percentageObj['Actual Change'] = parseInt(refinedData[i]['dailyconfirmed'], 10); 73 | percentageObj['Actial value'] = refinedData[i]['confirmed']; 74 | } 75 | 76 | brokenDownData.push(obj); 77 | percentageData.push(percentageObj); 78 | } 79 | 80 | 81 | // percentageData.push(percentageObj); 82 | } else { 83 | if (!loading) { 84 | const availableData = data[getProposedName(country)]; 85 | if (availableData) { 86 | refinedData = availableData.map(elem => { 87 | elem['active'] = (elem['confirmed'] - (elem['deaths'] + elem['recovered'])); 88 | return elem; 89 | }); 90 | } 91 | for (let i = 0; i 123 | { 124 | loading ? 125 | : 131 | refinedData.length === 0 ? 132 |

No time-series data available for this country

: 133 |
134 | 135 | {country !== 'India' ? 136 | : null } 137 |
138 | 139 | 140 | Trends - Change of Confirmed vs Active vs Recovered vs Deaths 141 | Total count at the daily basis 142 | 143 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 |
159 |
160 | } 161 | 162 | 163 | ) 164 | }; 165 | 166 | export default TimeSeries; -------------------------------------------------------------------------------- /src/js/time-series/TimeSeriesBroken.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React, {useState} from 'react'; 8 | import { 9 | ResponsiveContainer, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, 10 | } from 'recharts'; 11 | import Card from 'react-bootstrap/Card'; 12 | import ButtonGroup from 'react-bootstrap/ButtonGroup'; 13 | import Button from 'react-bootstrap/Button'; 14 | 15 | const TimeSeriesBroken = props => { 16 | const data = props.data; 17 | const [type, setType] = useState('confirmed'); 18 | const [chartColor, setChartColor] = useState('#17A2B8'); 19 | const [btnState, setBtnState] = useState({ 20 | 'confirmed': true, 21 | 'active': false, 22 | 'recovered': false, 23 | 'deaths': false 24 | }); 25 | 26 | const handleTypeClick = (type, color) => { 27 | setType(type); 28 | setChartColor(color); 29 | let tempState = Object.assign({}, { 30 | 'confirmed': false, 31 | 'active': false, 32 | 'recovered': false, 33 | 'deaths': false 34 | }); 35 | tempState[type] = 'true'; 36 | setBtnState(tempState); 37 | 38 | } 39 | 40 | return ( 41 | 42 |
43 | 44 | 45 | 46 | Trends - Number of New Cases Found per Day 47 |
48 | 49 | 55 | 61 | 67 | 73 | 74 |
75 |
76 | Number of New cases reported daily basis 77 |
78 | 79 | 80 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
90 |
91 |
92 |
93 | ) 94 | }; 95 | 96 | export default TimeSeriesBroken; -------------------------------------------------------------------------------- /src/js/time-series/TimeSeriesPercentage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | import React from 'react'; 8 | import { 9 | ResponsiveContainer, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, 10 | } from 'recharts'; 11 | import Card from 'react-bootstrap/Card'; 12 | 13 | const TimeSeriesPercentage = props => { 14 | const data = props.data; 15 | 16 | const CustomTooltip = ({ active, payload, label }) => { 17 | if (active && payload[0]) { 18 | return ( 19 |
20 |
{`On ${label}`}
21 |

22 | New Cases Changed: {payload[0].payload['% Change']}% 23 |

24 |
25 |

26 | {`Total Cases: ${payload[0].payload['Actial value']}`}
27 | {`Change since last day: ${payload[0].payload['Actual Change']} Cases`} 28 |

29 |
30 | ); 31 | } 32 | 33 | return null; 34 | }; 35 | 36 | return( 37 |
38 | 39 | 40 | 41 | New Cases Trends - % Changes Per day 42 | 43 | Percentage(%) Changes seen in New Cases at the Daily Basis. 44 |
45 | 46 | 47 | 49 | 50 | 51 | 52 | }/> 53 | 54 | 55 | 56 |
57 |
58 |
59 |
60 | 61 | ) 62 | }; 63 | 64 | export default TimeSeriesPercentage; -------------------------------------------------------------------------------- /src/js/useFetch.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | /* 3 | * Created on Sun Apr 12 2020 4 | * 5 | * Copyright (c) 2020 https://tapasadhikary.com 6 | */ 7 | 8 | const useFetch = (inputURL) => { 9 | const [data, setData] = useState({}); 10 | const [loading, setLoading] = useState(true); 11 | const [url, setUrl] = useState(inputURL); 12 | 13 | async function fetchURL() { 14 | const response = await fetch(url); 15 | const json = await response.json(); 16 | 17 | setData(json); 18 | setLoading(false); 19 | } 20 | 21 | useEffect(() => { 22 | fetchURL(); 23 | }, [url]); 24 | 25 | return [ data, loading ]; 26 | }; 27 | 28 | export { useFetch }; -------------------------------------------------------------------------------- /src/js/utils/color_codes.js: -------------------------------------------------------------------------------- 1 | 2 | const COLOR_CODES = { 3 | 'CATEGORIES': { 4 | 'CONFIRMED': '#17A2B8', 5 | 'ACTIVE': '#FFC107', 6 | 'RECOVERED': '#28A745', 7 | 'DEATHS': '#DC3545' 8 | }, 9 | 'LOADER': '#00BFFF', 10 | 'RANDOM': { 11 | 'BLACK': '#000000', 12 | 'WHITE': '#FFFFFF', 13 | 'TEAL_LIKE': '#17A2B8', 14 | 'YELLOW_ORANGE': '#FFC107', 15 | 'GREEN_LIKE': '#28A745', 16 | 'RED_LIKE': '#DC3545', 17 | 'DARK_GREY': '#626567', 18 | 'BROWN_LIKE': '#BA4A00', 19 | 'DARK_GREEN_LIKE': '#0E6655', 20 | 'ORANGE_LIKE': '#FF5833', 21 | 'DARK_PURPLE': '#200A3D', 22 | 'ORANGE_LIKE_VARIANT': '#FFB433' 23 | } 24 | }; 25 | 26 | export default COLOR_CODES; -------------------------------------------------------------------------------- /src/js/utils/india_state_codes.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Created on Sun Apr 12 2020 3 | * 4 | * Copyright (c) 2020 https://tapasadhikary.com 5 | */ 6 | 7 | const INDIA_STATE_CODES = { 8 | "Maharashtra": "MH", 9 | "Kerala": "KL", 10 | "Karnataka": "KA", 11 | "Telangana": "TG", 12 | "Gujarat": "GJ", 13 | "Uttar Pradesh": "UP", 14 | "Rajasthan": "RJ", 15 | "Delhi": "DL", 16 | "Haryana": "HR", 17 | "Punjab": "PB", 18 | "Tamil Nadu": "TN", 19 | "Madhya Pradesh": "MP", 20 | "Ladakh": "LD", 21 | "Jammu and Kashmir": "JK", 22 | "Andhra Pradesh": "AP", 23 | "West Bengal": "WB", 24 | "Chandigarh": "CH", 25 | "Uttarakhand": "UK", 26 | "Bihar": "BR", 27 | "Himachal Pradesh": "HP", 28 | "Chhattisgarh": "CT", 29 | "Goa": "GA", 30 | "Odisha": "OR", 31 | "Puducherry": "PY", 32 | "Manipur": "MN", 33 | "Mizoram": "MZ", 34 | "Andaman and Nicobar Islands": "AN", 35 | "Assam": "AS", 36 | "Meghalaya": "ML", 37 | "Tripura": "TR", 38 | "Arunachal Pradesh": "AR", 39 | "Jharkhand": "JH", 40 | "Nagaland": "NL", 41 | "Sikkim": "SK", 42 | "Dadra and Nagar Haveli": "DN", 43 | "Daman and Diu": "DD", 44 | "Lakshadweep": "LD", 45 | "Dadra and Nagar Haveli and Daman and Diu": "DN", 46 | "State Unassigned": "SU" 47 | }; 48 | 49 | export default INDIA_STATE_CODES; -------------------------------------------------------------------------------- /src/js/utils/top-headlines.json: -------------------------------------------------------------------------------- 1 | {"status":"ok","totalResults":70,"articles":[{"source":{"id":null,"name":"Deccanherald.com"},"author":"Suraksha P","title":"Will do whatever it takes to ensure that all of us come out of this, says recovered Bengaluru COVID-19 patient - Deccan Herald","description":"Karnataka Medical Education Minister Dr K Sudhakar and Health Minister B Sriramulu symbolically launched the clinical trials for convalescent plasma therapy here on Saturday at Victoria Hospital in Bengaluru.  Two patients from the state who have recovered fr…","url":"https://www.deccanherald.com/city/top-bengaluru-stories/will-do-whatever-it-takes-to-ensure-that-all-of-us-come-out-of-this-says-recovered-bengaluru-covid-19-patient-829762.html","urlToImage":null,"publishedAt":"2020-04-25T10:07:38Z","content":"Karnataka Medical Education Minister Dr K Sudhakar and Health Minister B Sriramulu symbolically launched the clinical trials for convalescent plasma therapy here on Saturday at Victoria Hospital in Bengaluru. \r\nTwo patients from the state who have recovered f… [+2654 chars]"},{"source":{"id":"reuters","name":"Reuters"},"author":"Reuters Editorial","title":"'No evidence' yet that recovered COVID patients cannot be reinfected: WHO - Reuters India","description":"The World Health Organization (WHO) said on Saturday that there was currently \"no evidence\" that people who have recovered from COVID-19 and have antibodies are protected from a second coronavirus infection.","url":"https://in.reuters.com/article/health-coronavirus-who-idINKCN2270F9","urlToImage":null,"publishedAt":"2020-04-25T09:53:00Z","content":"GENEVA (Reuters) - The World Health Organization (WHO) said on Saturday that there was currently “no evidence” that people who have recovered from COVID-19 and have antibodies are protected from a second coronavirus infection. \r\nIn a scientific brief, the Uni… [+1753 chars]"},{"source":{"id":null,"name":"Ibtimes.co.in"},"author":"Nirmal Narayanan","title":"Is coronavirus sexually transmitted? Medical expert answers - International Business Times, India Edition","description":"A previous study report had suggested that men are more prone to the severity of coronavirus infection due to the presence of testicles in their body.","url":"https://www.ibtimes.co.in/coronavirus-sexually-transmitted-medical-expert-answers-818377","urlToImage":null,"publishedAt":"2020-04-25T09:40:27Z","content":"Top US vaccine expert was 'fired'\r\nThe novel coronavirus that originated in a Wuhan seafood market has been spreading chaos all across the globe for the past four months. With death toll nearing 2,00,000, Covid-19 has affected people in all countries irrespec… [+1912 chars]"},{"source":{"id":null,"name":"Livemint.com"},"author":"Bloomberg","title":"Why Europe’s capital has world’s highest virus death rate - Livemint","description":"Despite having only 11 million people, the country has reported more deaths from the disease than China.With some 57 fatalities per 100,000 inhabitants, it has the highest per-capita death rate in the world","url":"https://www.livemint.com/news/world/why-europe-s-capital-has-world-s-highest-virus-death-rate-11587806581013.html","urlToImage":null,"publishedAt":"2020-04-25T09:33:43Z","content":"In an art-deco building in the heart of Brussels, Belgiums leading scientists gather daily to announce the countrys coronavirus toll. Its been grim reading.Despite having only 11 million people, the country has reported more deaths from the disease than China… [+4515 chars]"},{"source":{"id":"google-news","name":"Google News"},"author":null,"title":"Cotton, natural silk, chiffon make best materials for homemade masks against COVID-19: Study - The Financial Express","description":null,"url":"https://news.google.com/__i/rss/rd/articles/CBMilAFodHRwczovL3d3dy5maW5hbmNpYWxleHByZXNzLmNvbS9saWZlc3R5bGUvaGVhbHRoL2NvdHRvbi1uYXR1cmFsLXNpbGstY2hpZmZvbi1tYWtlLWJlc3QtbWF0ZXJpYWxzLWZvci1ob21lbWFkZS1tYXNrcy1hZ2FpbnN0LWNvdmlkLTE5LXN0dWR5LzE5Mzk0NDYv0gGZAWh0dHBzOi8vd3d3LmZpbmFuY2lhbGV4cHJlc3MuY29tL2xpZmVzdHlsZS9oZWFsdGgvY290dG9uLW5hdHVyYWwtc2lsay1jaGlmZm9uLW1ha2UtYmVzdC1tYXRlcmlhbHMtZm9yLWhvbWVtYWRlLW1hc2tzLWFnYWluc3QtY292aWQtMTktc3R1ZHkvMTkzOTQ0Ni9saXRlLw?oc=5","urlToImage":null,"publishedAt":"2020-04-25T09:04:27Z","content":null},{"source":{"id":null,"name":"Youtube.com"},"author":null,"title":"Health workers are on the frontline of the COVID-19 pandemic - eNCA","description":"Health workers are on the frontline of the covid-19 pandemic, some get infected and even succumb to the virus. Retshidisitswe Kotane, who recently graduated,...","url":"https://www.youtube.com/watch?v=8ZrrAJkQu2w","urlToImage":null,"publishedAt":"2020-04-25T08:34:11Z","content":null},{"source":{"id":null,"name":"Thehealthsite.com"},"author":"Jahnavi Sarma","title":"Delhi enters stage 2 of COVID-19 transmission: Can we avoid stage 3? - TheHealthSite","description":"Though officials say that the situation is under control Delhi health minister says that the state is now in stage 2 of COVID-19 transmission.","url":"https://www.thehealthsite.com/news/delhi-enters-stage-2-of-covid-19-transmission-can-we-avoid-stage-3-741725/","urlToImage":null,"publishedAt":"2020-04-25T08:06:40Z","content":"The COVID-19 pandemic is claiming more and more victims in India and cases in the National capital has seen a surge with more than 1,500 people testing positive to the virus. The deadly contagion has so far claimed 53 victims in Delhi as far official reports.… [+3202 chars]"},{"source":{"id":null,"name":"Gulfnews.com"},"author":"AFP","title":"COVID-19: Does sunlight rapidly destroy the coronavirus? | Americas - Gulf News","description":"Experts urge caution after US department of homeland security makes claim","url":"https://gulfnews.com/world/americas/covid-19-does-sunlight-rapidly-destroy-the-coronavirus-1.1587801920020","urlToImage":null,"publishedAt":"2020-04-25T08:02:36Z","content":"Generic image used for illustrative purposes\r\n Image Credit: Pixabay\r\nWashington:  Does sunlight rapidly destroy the coronavirus? A White House presentation on a mysterious government study says so - but some scientists have called for caution as we await mor… [+4257 chars]"},{"source":{"id":null,"name":"Indiatoday.in"},"author":null,"title":"World Malaria Day 2020: Date, theme, history, slogans and quotes - India Today","description":"World Malaria Day or WMD is observed on April 25 every year. The day aimed at taking urgent action in the control of the deadly disease. The theme of World Malaria Day 2020 is \"Zero malaria starts with me.\"","url":"https://www.indiatoday.in/information/story/world-malaria-day-2020-date-theme-history-facts-slogans-and-quotes-1670910-2020-04-25","urlToImage":null,"publishedAt":"2020-04-25T07:21:55Z","content":"Malaria is a life-threatening disease which is caused by the bites of infected mosquitoes. It is the Female Anopheles mosquitoes who spread the Plasmodium parasite through their saliva, which causes malaria.\r\nHowever, it is a preventable and treatable infecti… [+4230 chars]"},{"source":{"id":null,"name":"Livemint.com"},"author":"ANI","title":"106-year-old woman who survived Spanish Flu, now beats coronavirus too - Livemint","description":"Ana del Valle is the oldest survivor of the pandemic outbreaks in Spain.Ana was born in October 1913 and in less than six months she will turn 107","url":"https://www.livemint.com/news/world/106-year-old-woman-who-survived-spanish-flu-now-beats-coronavirus-too-11587798144700.html","urlToImage":null,"publishedAt":"2020-04-25T07:15:52Z","content":"Madrid: We may have all heard that miracles do happen, but sadly not all of us have the chance to witness them in our daily lives, especially during a pandemic today which brings the world to a standstill.Citing a similar story of survival, The Olive Press, a… [+2495 chars]"},{"source":{"id":null,"name":"Indiatoday.in"},"author":null,"title":"e-Agenda AajTak: Not just stay at home but also do yoga at home, says Ramdev - India Today","description":"e-Agenda Aaj Tak: Yoga guru Ramdev said people should not just stay and work at home, but they must also perform yoga at home.","url":"https://www.indiatoday.in/india/story/e-agenda-aajtak-yoga-ramdev-coronavirus-pandemic-lockdown-1670908-2020-04-25","urlToImage":null,"publishedAt":"2020-04-25T06:56:14Z","content":"In the wake of the coronavirus pandemic and the nationwide lockdown, people should not just stay and work at home, but they must also perform yoga at home, said yoga guru Ramdev on Saturday.\r\nRamdev was speaking at a special session at the e-Agenda Aaj Tak.\r\n… [+1005 chars]"},{"source":{"id":null,"name":"Expresshealthcare.in"},"author":"Sanjiv Das","title":"Experts stress on radiology preparedness for COVID 19 - Express Healthcare","description":"Like any other health professionals, radiologists are doing their bit to safeguard their patients with limited resources.  It’s time they get ready to set protocol for preparedness during and post epidemicIn the wake of the global health crisis due t","url":"https://www.expresshealthcare.in/covid19-updates/experts-stress-on-radiology-preparedness-for-covid-19/419329/","urlToImage":null,"publishedAt":"2020-04-25T06:20:00Z","content":"Like any other health professionals, radiologists are doing their bit to safeguard their patients with limited resources.  Its time they get ready to set protocol for preparedness during and post epidemic\r\nIn the wake of the global health crisis due to COVID-… [+13798 chars]"},{"source":{"id":null,"name":"Firstpost.com"},"author":null,"title":"World Malaria Day 2020: WHO's anti-malaria campaign and target to eliminate malaria from 35 more... - Firstpost","description":"According to WHO reports, malaria affected more than 228 million people in the world in 2018 and killed about 405,000 people globally in the same year.","url":"https://www.firstpost.com/health/world-malaria-day-2020-whos-anti-malaria-campaign-and-target-to-eliminate-malaria-from-35-more-countries-by-2030-8298691.html","urlToImage":null,"publishedAt":"2020-04-25T06:06:06Z","content":null},{"source":{"id":null,"name":"Yourtango.com"},"author":"https://www.yourtango.com/users/nicole-pomarico","title":"Covid-19 Strokes: Coronavirus Is Causing Strokes In Young Adults, Doctors Warn - YourTango","description":"This is a pretty scary possible side effect of the virus.","url":"https://www.yourtango.com/2020333481/covid-19-strokes-in-young-adults","urlToImage":null,"publishedAt":"2020-04-25T05:43:17Z","content":"This is a pretty scary possible side effect of the virus.\r\nSo far, doctors have believed that coronavirus has had a more mild impact on young adults, but now, they've learned new information that could change that belief.\r\nNow that we're a few months into the… [+3510 chars]"},{"source":{"id":null,"name":"Youtube.com"},"author":null,"title":"World leaders to launch COVID-19 drugs, vaccine plan: WHO - ARIRANG NEWS","description":"WHO \"코로나19 치료제•백신 개발 협력안 제시\" World leaders have pledged to work together in a landmark collaboration, to speed up the development of drugs, tests and vaccine...","url":"https://www.youtube.com/watch?v=XC4JHNYFmk0","urlToImage":null,"publishedAt":"2020-04-25T04:57:01Z","content":"WHO \"19 \"\r\nWorld leaders have pledged to work together in a landmark collaboration, to speed up the development of drugs, tests and vaccines to diagnose and treat COVID-19.According to the World Health Organization on Friday, world leaders including French Pr… [+495 chars]"},{"source":{"id":null,"name":"Youtube.com"},"author":null,"title":"Paris: Sewers tested for COVID-19 concentration | France Coronavirus | World News - WION","description":"Paris: Sewers tested for COVID-19 concentration | France Coronavirus | World News In France, traces of the novel coronavirus were discovered in 4 out of 27 s...","url":"https://www.youtube.com/watch?v=4ZJVtFYyA58","urlToImage":null,"publishedAt":"2020-04-25T04:35:19Z","content":"Paris: Sewers tested for COVID-19 concentration | France Coronavirus | World News\r\nIn France, traces of the novel coronavirus were discovered in 4 out of 27 samples of the non-potable water, which is supplied in Paris.\r\n#ParisCoronavirus#FranceCoronavirusDeat… [+1130 chars]"},{"source":{"id":"the-hindu","name":"The Hindu"},"author":"Aswathi Pacha","title":"Stop villainising bats, say scientists and conservationists - The Hindu","description":"The mammals do not spread COVID-19, they say","url":"https://www.thehindu.com/sci-tech/energy-and-environment/stop-villainising-bats-say-scientists-and-conservationists/article31429962.ece","urlToImage":null,"publishedAt":"2020-04-25T04:24:55Z","content":"Unverified news and social media posts linking bats to the COVID-19 outbreak have led to widespread antipathy and there have been increasing incidents of the public destroying bat roosts and smoking them out. To raise awareness, 64 chiropterologists (those wh… [+2199 chars]"},{"source":{"id":null,"name":"News18.com"},"author":"News18","title":"Coronavirus Detected on Air Pollution Particles That May Carry It Over Long Distances, Scientists Warn - News18","description":"Leonardo Setti at the University of Bologna in Italy said it was imperative to investigate if the the coronavirus could be transported through air pollution.","url":"https://www.news18.com/news/world/coronavirus-detected-on-air-pollution-particles-that-may-carry-it-over-long-distances-scientists-warn-2591919.html","urlToImage":null,"publishedAt":"2020-04-25T03:39:15Z","content":"The novel coronavirus has been found on air pollution particles by scientists who are studying if this could allow the virus to advance longer distances, resulting in more number of people contracting it, The Guardian reported.\r\nThe work is still in the initi… [+2716 chars]"},{"source":{"id":null,"name":"Hindustantimes.com"},"author":"Hindustan Times","title":"A month in lockdown, vaccines in human trials give hope: Covid-19 news today - Hindustan Times","description":"A preview of the important Covid-19 news from India and world today","url":"https://www.hindustantimes.com/india-news/a-month-in-lockdown-vaccines-in-human-trials-give-hope-covid-19-news-today/story-Y9XTbYJNVJFRhle8ubkTEL.html","urlToImage":null,"publishedAt":"2020-04-25T02:27:49Z","content":"India completes a month in lockdown on Saturday. In this period, the country has slowed the spread of the coronavirus disease (Covid-19) though many challenges still remain. Meanwhile, human trials of a vaccine developed by Oxford University has begun. An Ind… [+5596 chars]"},{"source":{"id":null,"name":"Ourbitcoinnews.com"},"author":null,"title":"Covid19, Second Wave of Corona May Hit India During Rainy Season – Corona Crisis: Second wave of Corona might hit India throughout monsoon - OBN","description":", , New Delhi Updated Sat, 25 Apr 2020 06:36 AM IST Listen to the information Even although India has restricted the affect of the…","url":"https://ourbitcoinnews.com/covid19-second-wave-of-corona-may-hit-india-during-rainy-season-corona-crisis-second-wave-of-corona-may-hit-india-during-monsoon/","urlToImage":null,"publishedAt":"2020-04-25T01:22:00Z","content":"Even although India has restricted the affect of the Corona virus epidemic thats wreaking havoc on a worldwide scale, the Indians might must face the second wave of the epidemic within the upcoming monsoon. Scientists have warned {that a} sudden enhance withi… [+1740 chars]"}]} -------------------------------------------------------------------------------- /src/js/utils/url.js: -------------------------------------------------------------------------------- 1 | 2 | const URL_INDIA_DISTRICT_DAILY = 'https://api.covid19india.org/districts_daily.json'; 3 | 4 | export { URL_INDIA_DISTRICT_DAILY }; 5 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const HtmlWebPackPlugin = require("html-webpack-plugin"); 4 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 5 | 6 | module.exports = { 7 | entry: './src/js/index.js', 8 | output: { 9 | filename: 'bundle.js', 10 | path: path.resolve(__dirname, 'dist'), 11 | publicPath: '/' 12 | }, 13 | 14 | devtool: 'source-map', 15 | 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.js$/, 20 | exclude: /node_modules/, 21 | use: { 22 | loader: "babel-loader" 23 | } 24 | }, 25 | { 26 | test: /\.html$/, 27 | use: [ 28 | { 29 | loader: "html-loader", 30 | options: { minimize: true } 31 | } 32 | ] 33 | }, 34 | { 35 | // Apply rule for .sass, .scss or .css files 36 | test: /\.(sa|sc|c)ss$/, 37 | // Set loaders to transform files. 38 | // Loaders are applying from right to left(!) 39 | // The first loader will be applied after others 40 | use: [ 41 | { 42 | // After all CSS loaders we use plugin to do his work. 43 | // It gets all transformed CSS and extracts it into separate 44 | // single bundled file 45 | loader: MiniCssExtractPlugin.loader 46 | }, 47 | { 48 | // This loader resolves url() and @imports inside CSS 49 | loader: "css-loader", 50 | }, 51 | { 52 | // Then we apply postCSS fixes like autoprefixer and minifying 53 | loader: "postcss-loader" 54 | }, 55 | { 56 | // First we transform SASS to standard CSS 57 | loader: "sass-loader" 58 | } 59 | ] 60 | }, 61 | { 62 | test: /\.(png|svg|jpg|gif)$/, 63 | use: [ 64 | 'file-loader' 65 | ] 66 | }, 67 | { 68 | // Apply rule for fonts files 69 | test: /\.(woff|woff2|ttf|otf|eot)$/, 70 | use: [ 71 | { 72 | // Using file-loader too 73 | loader: "file-loader", 74 | options: { 75 | outputPath: 'fonts' 76 | } 77 | } 78 | ] 79 | } 80 | ] 81 | }, 82 | plugins: [ 83 | new HtmlWebPackPlugin({ 84 | template: "./src/index.html", 85 | favicon: './assets/images/add_to_hs/favicon.ico', 86 | filename: "./index.html" 87 | }), 88 | new MiniCssExtractPlugin({ 89 | filename: "[name].css", 90 | chunkFilename: "[id].css" 91 | }) 92 | ], 93 | devServer: { 94 | historyApiFallback: true, 95 | contentBase: path.join(__dirname, "dist"), 96 | compress: true, 97 | port: 4000, 98 | proxy: { 99 | '/api': { 100 | target: 'http://localhost:1337', 101 | secure: false 102 | } 103 | } 104 | } 105 | }; --------------------------------------------------------------------------------