Skip to content

Commit 5988e02

Browse files
committed
init project with basic features
1 parent f44a4ae commit 5988e02

File tree

3 files changed

+544
-0
lines changed

3 files changed

+544
-0
lines changed

project/app.js

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// utils
2+
function $(selector) {
3+
return document.querySelector(selector);
4+
}
5+
function getUnixTimestamp(date) {
6+
return new Date(date).getTime();
7+
}
8+
9+
// DOM
10+
const confirmedTotal = $('.confirmed-total');
11+
const deathsTotal = $('.deaths');
12+
const recoveredTotal = $('.recovered');
13+
const lastUpdatedTime = $('.last-updated-time');
14+
const rankList = $('.rank-list');
15+
const deathsList = $('.deaths-list');
16+
const recoveredList = $('.recovered-list');
17+
const deathSpinner = createSpinnerElement('deaths-spinner');
18+
const recoveredSpinner = createSpinnerElement('recovered-spinner');
19+
20+
function createSpinnerElement(id) {
21+
const wrapperDiv = document.createElement('div');
22+
wrapperDiv.setAttribute('id', id);
23+
wrapperDiv.setAttribute(
24+
'class',
25+
'spinner-wrapper flex justify-center align-center',
26+
);
27+
const spinnerDiv = document.createElement('div');
28+
spinnerDiv.setAttribute('class', 'ripple-spinner');
29+
spinnerDiv.appendChild(document.createElement('div'));
30+
spinnerDiv.appendChild(document.createElement('div'));
31+
wrapperDiv.appendChild(spinnerDiv);
32+
return wrapperDiv;
33+
}
34+
35+
// state
36+
let isDeathLoading = false;
37+
let isRecoveredLoading = false;
38+
39+
// api
40+
function fetchCovidSummary() {
41+
const url = 'https://api.covid19api.com/summary';
42+
return axios.get(url);
43+
}
44+
45+
function fetchCountryInfo(countryCode, status) {
46+
// params: confirmed, recovered, deaths
47+
const url = `https://api.covid19api.com/country/${countryCode}/status/${status}`;
48+
return axios.get(url);
49+
}
50+
51+
// methods
52+
function startApp() {
53+
setupData();
54+
initEvents();
55+
}
56+
57+
// events
58+
function initEvents() {
59+
rankList.addEventListener('click', handleListClick);
60+
}
61+
62+
async function handleListClick(event) {
63+
let selectedId;
64+
if (
65+
event.target instanceof HTMLParagraphElement ||
66+
event.target instanceof HTMLSpanElement
67+
) {
68+
selectedId = event.target.parentElement.id;
69+
}
70+
if (event.target instanceof HTMLLIElement) {
71+
selectedId = event.target.id;
72+
}
73+
if (isDeathLoading) {
74+
return;
75+
}
76+
clearDeathList();
77+
clearRecoveredList();
78+
startLoadingAnimation();
79+
isDeathLoading = true;
80+
const { data: deathResponse } = await fetchCountryInfo(selectedId, 'deaths');
81+
const { data: recoveredResponse } = await fetchCountryInfo(
82+
selectedId,
83+
'recovered',
84+
);
85+
const { data: confirmedResponse } = await fetchCountryInfo(
86+
selectedId,
87+
'confirmed',
88+
);
89+
console.log(confirmedResponse);
90+
endLoadingAnimation();
91+
setDeathsList(deathResponse);
92+
setTotalDeathsByCountry(deathResponse);
93+
setRecoveredList(recoveredResponse);
94+
setTotalRecoveredByCountry(recoveredResponse);
95+
setChartData(confirmedResponse);
96+
isDeathLoading = false;
97+
// console.log(data);
98+
}
99+
100+
function setDeathsList(data) {
101+
const sorted = data.sort(
102+
(a, b) => getUnixTimestamp(b.Date) - getUnixTimestamp(a.Date),
103+
);
104+
sorted.forEach(value => {
105+
const li = document.createElement('li');
106+
li.setAttribute('class', 'list-item-b flex align-center');
107+
const span = document.createElement('span');
108+
span.textContent = value.Cases;
109+
span.setAttribute('class', 'deaths');
110+
const p = document.createElement('p');
111+
p.textContent = new Date(value.Date).toLocaleDateString().slice(0, -1);
112+
li.appendChild(span);
113+
li.appendChild(p);
114+
deathsList.appendChild(li);
115+
});
116+
}
117+
118+
function clearDeathList() {
119+
deathsList.innerHTML = null;
120+
}
121+
122+
function setTotalDeathsByCountry(data) {
123+
deathsTotal.innerText = data[0].Cases;
124+
}
125+
126+
function setRecoveredList(data) {
127+
const sorted = data.sort(
128+
(a, b) => getUnixTimestamp(b.Date) - getUnixTimestamp(a.Date),
129+
);
130+
sorted.forEach(value => {
131+
const li = document.createElement('li');
132+
li.setAttribute('class', 'list-item-b flex align-center');
133+
const span = document.createElement('span');
134+
span.textContent = value.Cases;
135+
span.setAttribute('class', 'recovered');
136+
const p = document.createElement('p');
137+
p.textContent = new Date(value.Date).toLocaleDateString().slice(0, -1);
138+
li.appendChild(span);
139+
li.appendChild(p);
140+
recoveredList.appendChild(li);
141+
});
142+
}
143+
144+
function clearRecoveredList() {
145+
recoveredList.innerHTML = null;
146+
}
147+
148+
function setTotalRecoveredByCountry(data) {
149+
recoveredTotal.innerText = data[0].Cases;
150+
}
151+
152+
function startLoadingAnimation() {
153+
deathsList.appendChild(deathSpinner);
154+
recoveredList.appendChild(recoveredSpinner);
155+
}
156+
157+
function endLoadingAnimation() {
158+
deathsList.removeChild(deathSpinner);
159+
recoveredList.removeChild(recoveredSpinner);
160+
}
161+
162+
//
163+
async function setupData() {
164+
const { data } = await fetchCovidSummary();
165+
console.log(data);
166+
setTotalConfirmedNumber(data);
167+
setTotalDeathsByWorld(data);
168+
setTotalRecoveredByWorld(data);
169+
setCountryRanksByConfirmedCases(data);
170+
setLastUpdatedTimestamp(data);
171+
// renderChart();
172+
}
173+
174+
function renderChart(data, labels) {
175+
var ctx = $('#lineChart').getContext('2d');
176+
const defaultLabel = [
177+
'January',
178+
'February',
179+
'March',
180+
'April',
181+
'May',
182+
'June',
183+
'July',
184+
];
185+
const defaultData = [0, 10, 5, 2, 20, 30, 45];
186+
Chart.defaults.global.defaultFontColor = '#f5eaea';
187+
Chart.defaults.global.defaultFontFamily = 'Exo 2';
188+
var chart = new Chart(ctx, {
189+
type: 'line',
190+
data: {
191+
labels,
192+
datasets: [
193+
{
194+
label: 'Confirmed for the last two weeks',
195+
backgroundColor: '#feb72b',
196+
borderColor: '#feb72b',
197+
data,
198+
},
199+
],
200+
},
201+
options: {},
202+
});
203+
}
204+
205+
function setChartData(data) {
206+
const chartData = data.slice(-14).map(value => value.Cases);
207+
const chartLabel = data
208+
.slice(-14)
209+
.map(value => new Date(value.Date).toLocaleDateString().slice(5, -1));
210+
renderChart(chartData, chartLabel);
211+
}
212+
213+
function setTotalConfirmedNumber(data) {
214+
confirmedTotal.innerText = data.Countries.reduce(
215+
(total, current) => (total += current.TotalConfirmed),
216+
0,
217+
);
218+
}
219+
220+
function setTotalDeathsByWorld(data) {
221+
deathsTotal.innerText = data.Countries.reduce(
222+
(total, current) => (total += current.TotalDeaths),
223+
0,
224+
);
225+
}
226+
227+
function setTotalRecoveredByWorld(data) {
228+
recoveredTotal.innerText = data.Countries.reduce(
229+
(total, current) => (total += current.TotalRecovered),
230+
0,
231+
);
232+
}
233+
234+
function setCountryRanksByConfirmedCases(data) {
235+
const sorted = data.Countries.sort(
236+
(a, b) => b.TotalConfirmed - a.TotalConfirmed,
237+
);
238+
sorted.forEach(value => {
239+
const li = document.createElement('li');
240+
li.setAttribute('class', 'list-item flex align-center');
241+
li.setAttribute('id', value.Slug);
242+
const span = document.createElement('span');
243+
span.textContent = value.TotalConfirmed;
244+
span.setAttribute('class', 'cases');
245+
const p = document.createElement('p');
246+
p.setAttribute('class', 'country');
247+
p.textContent = value.Country;
248+
li.appendChild(span);
249+
li.appendChild(p);
250+
rankList.appendChild(li);
251+
});
252+
}
253+
254+
function setLastUpdatedTimestamp(data) {
255+
lastUpdatedTime.innerText = new Date(data.Date).toLocaleString();
256+
}
257+
258+
startApp();

project/index.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>코로나 세계 현황</title>
7+
<link
8+
href="https://fonts.googleapis.com/css?family=Exo+2&display=swap"
9+
rel="stylesheet"
10+
/>
11+
<link rel="stylesheet" href="./main.css" />
12+
</head>
13+
<body>
14+
<header class="flex justify-center">
15+
<h1>코로나 세계 현황판</h1>
16+
</header>
17+
<main class="flex">
18+
<div class="left-panel flex column">
19+
<div class="total-board">
20+
<p>Total Confirmed</p>
21+
<span class="confirmed-total"></span>
22+
</div>
23+
<div class="country-ranks">
24+
<p>Confirmed Cases by Country</p>
25+
<ol class="rank-list"></ol>
26+
</div>
27+
<p class="last-updated-time flex justify-center align-center"></p>
28+
</div>
29+
<div class="right-panel">
30+
<div class="summary-wrapper flex">
31+
<div class="deaths-container">
32+
<h3 class="summary-title">Total Deaths</h3>
33+
<p class="total deaths">0</p>
34+
<div class="list-wrapper">
35+
<ol class="deaths-list"></ol>
36+
</div>
37+
</div>
38+
<div class="recovered-container">
39+
<h3 class="summary-title">Total Recovered</h3>
40+
<p class="total recovered">0</p>
41+
<div class="list-wrapper">
42+
<ol class="recovered-list"></ol>
43+
</div>
44+
</div>
45+
</div>
46+
<div class="chart-container">
47+
<canvas
48+
id="lineChart"
49+
class="corona-chart"
50+
style="width: 100%; height: 356px; background-color: #5b5656;"
51+
></canvas>
52+
</div>
53+
</div>
54+
</main>
55+
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
56+
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
57+
<script src="./app.js"></script>
58+
</body>
59+
</html>

0 commit comments

Comments
 (0)