Skip to content

Commit

Permalink
Merge pull request #26 from carlaiau/recoveries-basic-restructure
Browse files Browse the repository at this point in the history
Recoveries basic restructure
  • Loading branch information
carlaiau authored Apr 9, 2020
2 parents cca724b + 4e3d869 commit 6d5f153
Show file tree
Hide file tree
Showing 22 changed files with 73,874 additions and 159,142 deletions.
119,279 changes: 38,941 additions & 80,338 deletions client/data/advanced.json

Large diffs are not rendered by default.

7,198 changes: 6,967 additions & 231 deletions client/data/countries.json

Large diffs are not rendered by default.

105,633 changes: 27,478 additions & 78,155 deletions client/data/cumulative.json

Large diffs are not rendered by default.

61 changes: 53 additions & 8 deletions client/src/components/advanced-country-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export default class AdvancedCountryPage extends React.Component{
field: full_field_name
})

const latest = active_country.time_series[active_country.time_series.length - 1]

active_country.name = this.props.country_name


Expand All @@ -60,10 +62,11 @@ export default class AdvancedCountryPage extends React.Component{
<SEO title={`${this.props.country_name} COVID-19 Update: ${this.state.area_label} level cumulative graphs and comparisons`}/>
<section className="section" style={{paddingBottom: 0}}>
<div className="container">
<div className="columns info" style={{alignItems: 'flex-end'}}>
<div className="columns info" style={{justifyContent: 'space-between', alignItems: 'center'}}>
<div className="column is-half">
<h2 className="is-size-3 title">{this.props.country_name}</h2>
<table className="subtitle">
<tbody>
<tr>
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>{this.tidyFormat(country.highest_confirmed)}</th>
<td className="is-size-4">Cases</td>
Expand All @@ -74,10 +77,51 @@ export default class AdvancedCountryPage extends React.Component{
<td className="is-size-4">Deaths</td>
</tr>
:<></> }
{country.highest_recovered ?
<tr>
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>{this.tidyFormat(country.highest_recovered)}</th>
<td className="is-size-4">Recovered</td>
</tr>
:<></> }
</tbody>
</table>
</div>
<div className="column is-narrow">
<table>
<tbody>
<tr>
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>{this.tidyFormat(latest.confirmed_per_mil.toFixed(0))}</th>
<td className="is-size-4">Cases per million</td>
</tr>
{active_country.highest_deaths && active_country.highest_deaths > 1 ?
<tr>
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>{this.tidyFormat(latest.deaths_per_mil.toFixed(0))}</th>
<td className="is-size-4">Deaths per million</td>
</tr>
:<></> }
<tr >
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>
{this.tidyFormat(((latest.recovered / latest.confirmed) * 100).toFixed(0))}%
</th>
<td className="is-size-4">Recovered</td>
</tr>
{active_country.highest_deaths && active_country.highest_deaths > 1 ?
<tr>
<th className="is-size-4" style={{paddingRight: '10px', textAlign: 'right'}}>
{this.tidyFormat(((latest.deaths / latest.confirmed) * 100).toFixed(0))}%
</th>
<td className="is-size-4">Died</td>
</tr>
:<></> }
</tbody>

</table>

</div>
<div className="column is-half text-right-align-desktop">
<p className="is-size-7">
</div>
<div className="columns">
<div className="column is-half">
<p className="is-size-7" style={{marginBottom: '10px'}}>
Global data updated at <strong>{update_times.global}</strong>
</p>
{this.props.country_name == 'United States' ?
Expand All @@ -88,7 +132,8 @@ export default class AdvancedCountryPage extends React.Component{
{this.props.country_name == 'United States' ?
<p className="is-size-7">
The United States data is sourced from the
{' '}<a href="https://covidtracking.com/" target="_blank" rel="noopener noreferrer">
{' '}<a href="https://covidtracking.com/" target="_blank" rel="noopener noreferrer"
style={{fontWeight: 'bold', color: "#363636"}}>
COVID Tracking Project</a>.
</p>
: <></>}
Expand Down Expand Up @@ -133,8 +178,8 @@ export default class AdvancedCountryPage extends React.Component{
field="confirmed"
type_of_area="state"
checkedAreas={this.props.checkedAreas}
accumulateFrom={100}
accumulateOptions={[50, 100, 200, 300, 400, 500, 750, 1000]}
accumulateFrom={500}
accumulateOptions={[100, 250, 500, 1000, 5000]}
max_area_count={this.state.max_area_count}


Expand All @@ -156,8 +201,8 @@ export default class AdvancedCountryPage extends React.Component{
field="deaths"
type_of_area="state"
checkedAreas={this.props.checkedAreas}
accumulateFrom={10}
accumulateOptions={[10, 20, 30, 40, 50, 75, 100]}
accumulateFrom={50}
accumulateOptions={[10, 50, 100, 250, 500]}
/>
</>
}
Expand Down
119 changes: 65 additions & 54 deletions client/src/components/country-overview-graph.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,92 @@
import React from 'react'
import SingularGraphTooltip from './graph-tooltip'
import { parseJSON, format } from "date-fns"
import {LineChart, Line, XAxis, YAxis, Tooltip, Legend, Label} from 'recharts'
import {AreaChart, Area, XAxis, YAxis, Tooltip, Legend, Label} from 'recharts'
import RegionalGraphTooltip from './regional-graph-tooltip'


const CountryOverviewGraph = ({active_country, field, full_field_name, width, height, scale}) => {
const CountryOverviewGraph = ({active_country, width, height, scale}) => {


const filteredData = active_country.time_series.filter(t => parseInt(t[field]) > 0)
const filteredData = active_country.time_series.filter(t => parseInt(t.confirmed) > 0)
const latestDay = filteredData[filteredData.length - 1]
filteredData.forEach(t => {
t.dateString = format(parseJSON(t.date), 'MMM dd')
})

// Add growth to the countryOverView too!
const growth_label = `${field =='confirmed' ? 'Cases' :'Deaths'} double every 3 days`

const growth_rate = 1.25992105

let found_for_growth = false
let exceeds_mil = false
if( (full_field_name == 'confirmed' && active_country.highest_confirmed >= 100) || (full_field_name == 'deaths' && active_country.highest_deaths >= 10) ){
filteredData.forEach( (t, i) => {
if(found_for_growth && ! exceeds_mil){
t.growth = (filteredData[i - 1].growth * growth_rate).toFixed(0)
if(t.growth > 1000000){
exceeds_mil = true
}
}
else if(!exceeds_mil){
if(t[field] >= ( field == 'confirmed' ? 100 : field == 'deaths' ? 10 : Infinity)){
found_for_growth = true
t.growth = t[field]
}
else{
t.growth = null
}
}
})
}
let has_tests = false
let has_confirmed = false
let has_hospitalized = false
let has_deaths = false
let has_recovered = false

filteredData.forEach((t,i) => {
t.dateString = format(parseJSON(t.date), 'MMM dd')
t.index = i

if(t.tests > 0) has_tests = true
else t.tests = null

if(t.confirmed > 0) has_confirmed = true
else t.confirmed = null

if(t.hospitalized > 0) has_hospitalized = true
else t.hospitalized = null

if(t.deaths > 0) has_deaths = true
else t.deaths = null

if(t.recovered > 0) has_recovered = true
else t.recovered = null

})

if(filteredData.length){
return (
<LineChart width={width} height={height} data={filteredData} margin={{ bottom: 25, top: 15, right: 10, left: 10 }}>
<AreaChart width={width} height={height} data={filteredData} margin={{ bottom: 25, top: 15, right: 10, left: 10 }}>
<XAxis
dataKey="index"
name="Days"
type="number"
tickCount={8}
domain = {[0, latestDay.day]}
>
<Label value="Days since first confirmed case" offset={-15} position="insideBottom" />
</XAxis>

<YAxis width={55} scale={scale} domain={['auto', 'auto']} interval="preserveStart" tickCount={12}/>
{
full_field_name == 'confirmed' ?
<Line type="monotone" dataKey="confirmed" name="Total confirmed cases" stroke="#ff793f" dot={false} strokeWidth={3}/> :
full_field_name == 'deaths' ?
<Line type="monotone" dataKey="deaths" name="Total deaths" stroke="#ff5252"dot={false} strokeWidth={3}/>
:
full_field_name == 'confirmed_per_mil' ?
<Line type="monotone" dataKey="confirmed_per_mil" name="Confirmed cases per million" stroke="#ff793f" formatter={value => value.toFixed(2)}dot={false} strokeWidth={3}/>
:
<Line type="monotone" dataKey="deaths_per_mil" name="Deaths per million"stroke="#ff5252" formatter={value => value.toFixed(2)}dot={false} strokeWidth={3}/>
}
{
found_for_growth ?
<Line type="monotone" stroke='#aaa' name={growth_label} dataKey='growth' strokeOpacity={0.5} dot={false} strokeWidth={3} isAnimationActive={true}/>
:
<></>
}
<Tooltip content={SingularGraphTooltip}/>
<Legend verticalAlign="top" iconType="square"/>

{ has_tests ?
<Area type="monotone" dataKey="tests" name="Tests" stroke="#218c74" fillOpacity={1} fill="#218c74" dot={false} strokeWidth={1}/>
: <></> }
{ has_confirmed ?
<Area type="monotone" dataKey="confirmed" name="Confirmed" stroke="#227093" fillOpacity={1} fill="#227093" dot={false} strokeWidth={1}/>
: <></> }
{ has_hospitalized ?
<Area type="monotone" dataKey="hospitalized" name="Hospitalized" stroke="#ff793f" fillOpacity={1} fill="#ff793f" dot={false} strokeWidth={1}/>
: <></> }
{ has_deaths && has_recovered && latestDay.deaths < latestDay.recovered ?
<Area type="monotone" dataKey="recovered" name="Recovered" stroke="#2ecc71" fillOpacity={0.9} fill="#2ecc71" dot={false} strokeWidth={1}/>
: <></> }
{ has_deaths && has_recovered && latestDay.deaths < latestDay.recovered ?
<Area type="monotone" dataKey="deaths" name="Deaths" stroke="#ff5252" fillOpacity={0.9} fill="#ff5252" dot={false} strokeWidth={1}/>
: <></> }
{ has_deaths && has_recovered && latestDay.deaths > latestDay.recovered ?
<Area type="monotone" dataKey="deaths" name="Deaths" stroke="#ff5252" fillOpacity={0.9} fill="#ff5252" dot={false} strokeWidth={1}/>
: <></> }
{ has_deaths && has_recovered && latestDay.deaths > latestDay.recovered ?
<Area type="monotone" dataKey="recovered" name="Recovered" stroke="#2ecc71" fillOpacity={0.9} fill="#2ecc71" dot={false} strokeWidth={1}/>
: <></> }

</LineChart>
{ has_recovered && ! has_deaths ?
<Area type="monotone" dataKey="recovered" name="Recovered" stroke="#2ecc71" fillOpacity={1} fill="#2ecc71" dot={false} strokeWidth={1}/>
: <></> }
{ ! has_recovered && has_deaths ?
<Area type="monotone" dataKey="deaths" name="Deaths" stroke="#ff5252" fillOpacity={1} fill="#ff5252" dot={false} strokeWidth={1}/>
: <></> }
<Legend verticalAlign="top" iconType="square"/>
<Tooltip content={RegionalGraphTooltip}/>
</AreaChart>
)
}
return <p className="is-size-3"><strong>No Deaths!</strong></p>
}

export default CountryOverviewGraph
Loading

0 comments on commit 6d5f153

Please sign in to comment.