forked from joshua1988/learn-typescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f44a4ae
commit 5988e02
Showing
3 changed files
with
544 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
// utils | ||
function $(selector) { | ||
return document.querySelector(selector); | ||
} | ||
function getUnixTimestamp(date) { | ||
return new Date(date).getTime(); | ||
} | ||
|
||
// DOM | ||
const confirmedTotal = $('.confirmed-total'); | ||
const deathsTotal = $('.deaths'); | ||
const recoveredTotal = $('.recovered'); | ||
const lastUpdatedTime = $('.last-updated-time'); | ||
const rankList = $('.rank-list'); | ||
const deathsList = $('.deaths-list'); | ||
const recoveredList = $('.recovered-list'); | ||
const deathSpinner = createSpinnerElement('deaths-spinner'); | ||
const recoveredSpinner = createSpinnerElement('recovered-spinner'); | ||
|
||
function createSpinnerElement(id) { | ||
const wrapperDiv = document.createElement('div'); | ||
wrapperDiv.setAttribute('id', id); | ||
wrapperDiv.setAttribute( | ||
'class', | ||
'spinner-wrapper flex justify-center align-center', | ||
); | ||
const spinnerDiv = document.createElement('div'); | ||
spinnerDiv.setAttribute('class', 'ripple-spinner'); | ||
spinnerDiv.appendChild(document.createElement('div')); | ||
spinnerDiv.appendChild(document.createElement('div')); | ||
wrapperDiv.appendChild(spinnerDiv); | ||
return wrapperDiv; | ||
} | ||
|
||
// state | ||
let isDeathLoading = false; | ||
let isRecoveredLoading = false; | ||
|
||
// api | ||
function fetchCovidSummary() { | ||
const url = 'https://api.covid19api.com/summary'; | ||
return axios.get(url); | ||
} | ||
|
||
function fetchCountryInfo(countryCode, status) { | ||
// params: confirmed, recovered, deaths | ||
const url = `https://api.covid19api.com/country/${countryCode}/status/${status}`; | ||
return axios.get(url); | ||
} | ||
|
||
// methods | ||
function startApp() { | ||
setupData(); | ||
initEvents(); | ||
} | ||
|
||
// events | ||
function initEvents() { | ||
rankList.addEventListener('click', handleListClick); | ||
} | ||
|
||
async function handleListClick(event) { | ||
let selectedId; | ||
if ( | ||
event.target instanceof HTMLParagraphElement || | ||
event.target instanceof HTMLSpanElement | ||
) { | ||
selectedId = event.target.parentElement.id; | ||
} | ||
if (event.target instanceof HTMLLIElement) { | ||
selectedId = event.target.id; | ||
} | ||
if (isDeathLoading) { | ||
return; | ||
} | ||
clearDeathList(); | ||
clearRecoveredList(); | ||
startLoadingAnimation(); | ||
isDeathLoading = true; | ||
const { data: deathResponse } = await fetchCountryInfo(selectedId, 'deaths'); | ||
const { data: recoveredResponse } = await fetchCountryInfo( | ||
selectedId, | ||
'recovered', | ||
); | ||
const { data: confirmedResponse } = await fetchCountryInfo( | ||
selectedId, | ||
'confirmed', | ||
); | ||
console.log(confirmedResponse); | ||
endLoadingAnimation(); | ||
setDeathsList(deathResponse); | ||
setTotalDeathsByCountry(deathResponse); | ||
setRecoveredList(recoveredResponse); | ||
setTotalRecoveredByCountry(recoveredResponse); | ||
setChartData(confirmedResponse); | ||
isDeathLoading = false; | ||
// console.log(data); | ||
} | ||
|
||
function setDeathsList(data) { | ||
const sorted = data.sort( | ||
(a, b) => getUnixTimestamp(b.Date) - getUnixTimestamp(a.Date), | ||
); | ||
sorted.forEach(value => { | ||
const li = document.createElement('li'); | ||
li.setAttribute('class', 'list-item-b flex align-center'); | ||
const span = document.createElement('span'); | ||
span.textContent = value.Cases; | ||
span.setAttribute('class', 'deaths'); | ||
const p = document.createElement('p'); | ||
p.textContent = new Date(value.Date).toLocaleDateString().slice(0, -1); | ||
li.appendChild(span); | ||
li.appendChild(p); | ||
deathsList.appendChild(li); | ||
}); | ||
} | ||
|
||
function clearDeathList() { | ||
deathsList.innerHTML = null; | ||
} | ||
|
||
function setTotalDeathsByCountry(data) { | ||
deathsTotal.innerText = data[0].Cases; | ||
} | ||
|
||
function setRecoveredList(data) { | ||
const sorted = data.sort( | ||
(a, b) => getUnixTimestamp(b.Date) - getUnixTimestamp(a.Date), | ||
); | ||
sorted.forEach(value => { | ||
const li = document.createElement('li'); | ||
li.setAttribute('class', 'list-item-b flex align-center'); | ||
const span = document.createElement('span'); | ||
span.textContent = value.Cases; | ||
span.setAttribute('class', 'recovered'); | ||
const p = document.createElement('p'); | ||
p.textContent = new Date(value.Date).toLocaleDateString().slice(0, -1); | ||
li.appendChild(span); | ||
li.appendChild(p); | ||
recoveredList.appendChild(li); | ||
}); | ||
} | ||
|
||
function clearRecoveredList() { | ||
recoveredList.innerHTML = null; | ||
} | ||
|
||
function setTotalRecoveredByCountry(data) { | ||
recoveredTotal.innerText = data[0].Cases; | ||
} | ||
|
||
function startLoadingAnimation() { | ||
deathsList.appendChild(deathSpinner); | ||
recoveredList.appendChild(recoveredSpinner); | ||
} | ||
|
||
function endLoadingAnimation() { | ||
deathsList.removeChild(deathSpinner); | ||
recoveredList.removeChild(recoveredSpinner); | ||
} | ||
|
||
// | ||
async function setupData() { | ||
const { data } = await fetchCovidSummary(); | ||
console.log(data); | ||
setTotalConfirmedNumber(data); | ||
setTotalDeathsByWorld(data); | ||
setTotalRecoveredByWorld(data); | ||
setCountryRanksByConfirmedCases(data); | ||
setLastUpdatedTimestamp(data); | ||
// renderChart(); | ||
} | ||
|
||
function renderChart(data, labels) { | ||
var ctx = $('#lineChart').getContext('2d'); | ||
const defaultLabel = [ | ||
'January', | ||
'February', | ||
'March', | ||
'April', | ||
'May', | ||
'June', | ||
'July', | ||
]; | ||
const defaultData = [0, 10, 5, 2, 20, 30, 45]; | ||
Chart.defaults.global.defaultFontColor = '#f5eaea'; | ||
Chart.defaults.global.defaultFontFamily = 'Exo 2'; | ||
var chart = new Chart(ctx, { | ||
type: 'line', | ||
data: { | ||
labels, | ||
datasets: [ | ||
{ | ||
label: 'Confirmed for the last two weeks', | ||
backgroundColor: '#feb72b', | ||
borderColor: '#feb72b', | ||
data, | ||
}, | ||
], | ||
}, | ||
options: {}, | ||
}); | ||
} | ||
|
||
function setChartData(data) { | ||
const chartData = data.slice(-14).map(value => value.Cases); | ||
const chartLabel = data | ||
.slice(-14) | ||
.map(value => new Date(value.Date).toLocaleDateString().slice(5, -1)); | ||
renderChart(chartData, chartLabel); | ||
} | ||
|
||
function setTotalConfirmedNumber(data) { | ||
confirmedTotal.innerText = data.Countries.reduce( | ||
(total, current) => (total += current.TotalConfirmed), | ||
0, | ||
); | ||
} | ||
|
||
function setTotalDeathsByWorld(data) { | ||
deathsTotal.innerText = data.Countries.reduce( | ||
(total, current) => (total += current.TotalDeaths), | ||
0, | ||
); | ||
} | ||
|
||
function setTotalRecoveredByWorld(data) { | ||
recoveredTotal.innerText = data.Countries.reduce( | ||
(total, current) => (total += current.TotalRecovered), | ||
0, | ||
); | ||
} | ||
|
||
function setCountryRanksByConfirmedCases(data) { | ||
const sorted = data.Countries.sort( | ||
(a, b) => b.TotalConfirmed - a.TotalConfirmed, | ||
); | ||
sorted.forEach(value => { | ||
const li = document.createElement('li'); | ||
li.setAttribute('class', 'list-item flex align-center'); | ||
li.setAttribute('id', value.Slug); | ||
const span = document.createElement('span'); | ||
span.textContent = value.TotalConfirmed; | ||
span.setAttribute('class', 'cases'); | ||
const p = document.createElement('p'); | ||
p.setAttribute('class', 'country'); | ||
p.textContent = value.Country; | ||
li.appendChild(span); | ||
li.appendChild(p); | ||
rankList.appendChild(li); | ||
}); | ||
} | ||
|
||
function setLastUpdatedTimestamp(data) { | ||
lastUpdatedTime.innerText = new Date(data.Date).toLocaleString(); | ||
} | ||
|
||
startApp(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>코로나 세계 현황</title> | ||
<link | ||
href="https://fonts.googleapis.com/css?family=Exo+2&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<link rel="stylesheet" href="./main.css" /> | ||
</head> | ||
<body> | ||
<header class="flex justify-center"> | ||
<h1>코로나 세계 현황판</h1> | ||
</header> | ||
<main class="flex"> | ||
<div class="left-panel flex column"> | ||
<div class="total-board"> | ||
<p>Total Confirmed</p> | ||
<span class="confirmed-total"></span> | ||
</div> | ||
<div class="country-ranks"> | ||
<p>Confirmed Cases by Country</p> | ||
<ol class="rank-list"></ol> | ||
</div> | ||
<p class="last-updated-time flex justify-center align-center"></p> | ||
</div> | ||
<div class="right-panel"> | ||
<div class="summary-wrapper flex"> | ||
<div class="deaths-container"> | ||
<h3 class="summary-title">Total Deaths</h3> | ||
<p class="total deaths">0</p> | ||
<div class="list-wrapper"> | ||
<ol class="deaths-list"></ol> | ||
</div> | ||
</div> | ||
<div class="recovered-container"> | ||
<h3 class="summary-title">Total Recovered</h3> | ||
<p class="total recovered">0</p> | ||
<div class="list-wrapper"> | ||
<ol class="recovered-list"></ol> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="chart-container"> | ||
<canvas | ||
id="lineChart" | ||
class="corona-chart" | ||
style="width: 100%; height: 356px; background-color: #5b5656;" | ||
></canvas> | ||
</div> | ||
</div> | ||
</main> | ||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script> | ||
<script src="./app.js"></script> | ||
</body> | ||
</html> |
Oops, something went wrong.