Skip to content

Commit

Permalink
-- Adds new sources of data https://github.com/andrab/ecuacovid
Browse files Browse the repository at this point in the history
  • Loading branch information
Cesar Cobo committed May 9, 2020
1 parent 0ab4fb8 commit aed29df
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 34 deletions.
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ Para desarrolladoras/es:
REACT_APP_MAPBOX_ACCESS_TOKEN=token
```

- Crear dos tablas en Airtable, se pueden crear importando los siguientes CSV de ejemplo:
- [Datos de provincias](https://github.com/SerotoninaAbad/covid19-csv-examples/blob/master/province-data.csv)
- [Totales diarios](https://github.com/SerotoninaAbad/covid19-csv-examples/blob/master/daily-totals.csv)
- Añadir a `/.env.local` la API key de Airtable y los 2 endpoints para consultar las tablas creadas
- Agregar urls para datos de provincia y totales en Ecuador:
```
REACT_APP_AIRTABLE_API_KEY=airtable_key
REACT_APP_PROVINCE_STATS_ENDPOINT=airtable_provinces_endpoint
REACT_APP_TOTAL_STATS_ENDPOINT=airtable_total_stats_endpoint
REACT_APP_PROVINCE_STATS_ENDPOINT=https://raw.githubusercontent.com/andrab/ecuacovid/master/datos_crudos/positivas/por_fecha/provincias_por_dia.csv
REACT_APP_TOTAL_STATS_ENDPOINT=https://raw.githubusercontent.com/andrab/ecuacovid/master/datos_crudos/ecuacovid.json
```


Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@reach/router": "^1.3.3",
"chart.js": "^2.9.3",
"d3": "^5.16.0",
"papaparse": "^5.2.0",
"react": "^16.13.1",
"react-chartjs-2": "^2.9.0",
"react-dom": "^16.13.1",
Expand Down
11 changes: 5 additions & 6 deletions src/components/Ecuador.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ const Ecuador = ({ t }) => {
return b.confirmed - a.confirmed;
});

const dateInArray = lastDayTotals.date.split('-');
const date = `${dateInArray[2]}.${dateInArray[1]}`;
const date = lastDayTotals.date;
var confirmedDiff = lastDayTotals.confirmed - prevDayTotals.confirmed;
var deathsDiff = lastDayTotals.deaths - prevDayTotals.deaths;
var possibleDeathsDiff =
Expand Down Expand Up @@ -127,17 +126,17 @@ const Ecuador = ({ t }) => {
<p>{lastDayTotals.negatives}</p>
<h3>{t('negatives.label')}</h3>
</StatBlock>
<StatBlock>
{/* <StatBlock> //TODO: Implement services to look for recoveries
<span>
{isPositive(recoveriesDiff) ? '+' : ''}
{recoveriesDiff}
</span>
<p>{lastDayTotals.recoveries}</p>
<h3>{t('recoveries.label')}</h3>
</StatBlock>
</StatBlock> */}
</StatGrid>

<StatGrid>
{/* <StatGrid> //TODO: Implement services to look for tests
<StatBlock>
<span>
{isPositive(testsDiff) ? '+' : ''}
Expand Down Expand Up @@ -170,7 +169,7 @@ const Ecuador = ({ t }) => {
<p>{positiveRatio.toFixed(2)}% </p>
<h3>{t('rate.label')}</h3>
</StatBlock>
</StatGrid>
</StatGrid> */}

<HeaderContainer>
<h4>{t('confirmedPerRegion.label')}</h4>
Expand Down
34 changes: 21 additions & 13 deletions src/hooks/statsContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useContext } from 'react';
import LoadingPage from '../components/LoadingPage';
import ErrorPage from '../components/ErrorPage';
import useFetch from './useFetch';
import useCSVParser from './useCSVParser';
import { parseProvincesFromCSVJSON } from '../utils/parser';

const AIRTABLE_API_KEY = process.env.REACT_APP_AIRTABLE_API_KEY;
const PROVINCE_STATS_ENDPOINT = process.env.REACT_APP_PROVINCE_STATS_ENDPOINT;
Expand All @@ -10,14 +12,13 @@ const TOTAL_STATS_ENDPOINT = process.env.REACT_APP_TOTAL_STATS_ENDPOINT;
const StatsContext = React.createContext([]);

const StatsProvider = ({ children }) => {
const { data, isLoading, isError } = useFetch(
const { data, isLoading, isError } = useCSVParser(
{
url: PROVINCE_STATS_ENDPOINT,
apiKey: AIRTABLE_API_KEY
},
{ records: [] }
);
const provinces = data.records.map(item => ({ ...item.fields }));
const provinces = parseProvincesFromCSVJSON(data)

const {
data: dailyRecords,
Expand All @@ -26,24 +27,29 @@ const StatsProvider = ({ children }) => {
} = useFetch(
{
url: TOTAL_STATS_ENDPOINT,
apiKey: AIRTABLE_API_KEY
},
{ records: [] }
[]
);
const dailyTotals = dailyRecords.records.map(item => ({
...item.fields

const dailyTotals = dailyRecords.map(item => ({
deaths: item.total_muertes,
confirmed: item.positivas,
possibleDeaths: item.muertes_probables,
negatives: item.negativas,
date: item.created_at
}));

let lastDayTotals;
let prevDayTotals;
let beforeYesterdayTotals;
if (dailyTotals.length) {
lastDayTotals = { ...dailyTotals[dailyTotals.length - 1] };
prevDayTotals = { ...dailyTotals[dailyTotals.length - 2] };
const dailyTotalsLength = dailyTotals.length
if (dailyTotalsLength > 0) {
lastDayTotals = { ...dailyTotals[dailyTotalsLength - 1] };
prevDayTotals = { ...dailyTotals[dailyTotalsLength - 2] };
beforeYesterdayTotals = { ...dailyTotals[dailyTotals.length - 3] };
} else {
lastDayTotals = {
date: '0000-00-00',
date: '0000/00/00',
tiime: '00:00',
confirmed: 0,
deaths: 0,
Expand All @@ -55,10 +61,12 @@ const StatsProvider = ({ children }) => {
hospitalStable: 0,
reserveState: 0
};
prevDayTotals = lastDayTotals
beforeYesterdayTotals = lastDayTotals
}

const generalIsLoading = isLoading || dailyIsLoading;
const generalIsError = isError || dailyIsError;
const generalIsLoading = isLoading;
const generalIsError = isError;

if (generalIsError) {
return <ErrorPage />;
Expand Down
37 changes: 37 additions & 0 deletions src/hooks/useCSVParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useState, useEffect } from 'react';
import { getCSVFile } from '../utils/parser';

export default function useCSVParser({ url }, initialData = null) {
const [data, setData] = useState(initialData);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);

useEffect(() => {
let didCancel = false;
async function fetchData() {
setIsLoading(true);
setIsError(false);

try {
const data = await getCSVFile(url)
setData(data);
setIsLoading(false);
} catch (err) {
if (!didCancel) {
setIsError(true);
setIsLoading(false);
}
}
}
fetchData();

return () => {
didCancel = true;
};
}, [url]);
return {
data,
isLoading,
isError
};
}
11 changes: 3 additions & 8 deletions src/hooks/useFetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,9 @@ export default function useFetch({ url, apiKey = null }, initialData = null) {
setIsError(false);

let options = {};
const headers = new Headers();
if (apiKey) {
headers.set('Authorization', `Bearer ${apiKey}`);
options = {
method: 'GET',
headers
};
}
options = {
method: 'GET',
};

try {
const response = await fetch(url, options);
Expand Down
46 changes: 46 additions & 0 deletions src/utils/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Papa from 'papaparse'

export const parseProvincesFromCSVJSON = (csvJSON) => {
const parsedProvinces = []
if(csvJSON && csvJSON.length > 0) {
const headers = csvJSON[0];
const headersLength = headers.length;
const provinces = [...csvJSON];
delete provinces[0]
provinces.forEach((province, index) => {
const provinceItem = {
id: index,
name: province[0],
confirmed: province[headersLength - 1],
lat: parseFloat(province[2]),
lng: parseFloat(province[3]),
status: getStatus(province[headersLength - 1]),
}
parsedProvinces.push(provinceItem)
});
}

return parsedProvinces;
};

export const getCSVFile = (url) => new Promise( (resolve, reject) => {
Papa.parse(url, {
download: true,
complete: (parsed) => {
resolve(parsed.data);
},
error: (e) => {
reject(e);
}
})
});

const getStatus = (confirmed) => {
if(confirmed > 5000) {
return 'alert';
} else if(confirmed > 1500) {
return 'warning';
} else if(confirmed > 500) {
return 'caution';
}
};

0 comments on commit aed29df

Please sign in to comment.