-
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
e0aa141
commit fc46197
Showing
17 changed files
with
1,105 additions
and
2,175 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
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 |
---|---|---|
@@ -1,122 +1,77 @@ | ||
import * as React from "react"; | ||
import ReactGlobe, { Marker } from "react-globe"; | ||
|
||
import markers from "./markers"; | ||
import markerRenderer from "./markerRenderer"; | ||
import worldTexture from "./assets/world.jpg"; | ||
import "./styles.css"; | ||
import { useState, useEffect } from "react"; | ||
import { Object3D } from "three"; | ||
import { initGlobe } from "./Globe"; | ||
import { GlobalCounts } from "./GlobalCounts"; | ||
import { Counter } from "./Counter"; | ||
import { Spinner } from "./Spinner"; | ||
import globalData from "./assets/global.json"; | ||
|
||
function getWindowDimensions() { | ||
const { innerWidth: width, innerHeight: height } = window; | ||
return { | ||
width, | ||
height, | ||
}; | ||
} | ||
|
||
export default function App() { | ||
const [details, setDetails] = useState<any>(null); | ||
const [isLoaded, onTextureLoaded] = useState(false); | ||
const [cameraOptions, setCameraOptions] = useState({ | ||
maxDistanceRadiusScale: 100, | ||
autoRotateSpeed: 0.1, | ||
distanceRadiusScale: 100, | ||
}); | ||
|
||
const [windowDimensions, setWindowDimensions] = useState( | ||
getWindowDimensions() | ||
); | ||
const [totals, setTotals] = useState<number[]>([]); | ||
|
||
function getTooltipContent(marker: Marker) { | ||
return `Location: ${marker.Country} (Active Cases: ${marker.activeCases})`; | ||
} | ||
|
||
function onClickMarker( | ||
marker: Marker, | ||
markerObject?: Object3D, | ||
event?: PointerEvent | ||
) { | ||
zoomOut(); | ||
setDetails(getTooltipContent(marker)); | ||
} | ||
|
||
function onDefocus(previousCoordinates: any, event?: PointerEvent) { | ||
setDetails(null); | ||
} | ||
|
||
const zoomOut = () => { | ||
useEffect(() => initGlobe(), []); | ||
useEffect(() => { | ||
setTimeout(() => { | ||
if (windowDimensions.width <= 500) { | ||
setDetails(null); | ||
} | ||
let total: number[] = []; | ||
total.push(GlobalCounts.totalConfirmed); | ||
total.push(GlobalCounts.totalDeaths); | ||
total.push(GlobalCounts.totalRecoveries); | ||
total.push(GlobalCounts.totalActive); | ||
setTotals(total); | ||
}, 3000); | ||
}; | ||
|
||
}, [GlobalCounts.set]); | ||
return ( | ||
<React.Fragment> | ||
<Spinner loaded={isLoaded} /> | ||
<div className="header1">COVID19 Globe Tracker</div> | ||
<div className="header2">Active Cases</div> | ||
<div className="globe"> | ||
<ReactGlobe | ||
markers={markers} | ||
markerOptions={{ renderer: markerRenderer }} | ||
onDefocus={onDefocus} | ||
onClickMarker={onClickMarker} | ||
onMouseOverMarker={onClickMarker} | ||
onMouseOutMarker={() => setDetails(null)} | ||
cameraOptions={{ | ||
maxDistanceRadiusScale: 100, | ||
autoRotateSpeed: 1.0, | ||
distanceRadiusScale: 100, | ||
}} | ||
focusOptions={{ | ||
distanceRadiusScale: 30, | ||
enableDefocus: true, | ||
}} | ||
globeOptions={{ | ||
texture: worldTexture, | ||
glowColor: "red", | ||
enableClouds: false, | ||
}} | ||
onTextureLoaded={() => onTextureLoaded(true)} | ||
/> | ||
{details && ( | ||
<div className="details"> | ||
<p> {details}</p> | ||
</div> | ||
)} | ||
<div id="globeViz"></div> | ||
<div className="top-info-container"> | ||
<div className="title">COVID-19</div> | ||
<div className="title-desc"> | ||
Loading countries affected by the virus... | ||
</div> | ||
</div> | ||
{isLoaded ? ( | ||
<div className="footer"> | ||
<Counter /> | ||
<div className="bottom-info-container"> | ||
<Spinner loaded={GlobalCounts.set} /> | ||
{GlobalCounts.set ? ( | ||
<> | ||
<div | ||
style={{ fontSize: "14px", color: "#ccd6f6", marginTop: "35px" }} | ||
> | ||
Total Counts <span className="updated"></span> | ||
</div> | ||
<div style={{ color: "#e6f1ff", padding: "0 5px" }}> | ||
<span id="infected"> | ||
INFECTED: | ||
<Counter count={totals[0]} /> | ||
</span> | ||
<span id="deaths"> | ||
{" "} | ||
• DEATHS: | ||
<Counter count={totals[1]} /> | ||
</span> | ||
<span id="recovered"> | ||
{" "} | ||
• RECOVERED: | ||
<Counter count={totals[2]} /> | ||
</span> | ||
<span id="active"> | ||
{" "} | ||
• ACTIVE: | ||
<Counter count={totals[3]} /> | ||
</span> | ||
</div> | ||
</> | ||
) : null} | ||
<div style={{ marginTop: "5px" }}> | ||
<a | ||
href="https://github.com/tanmaylaud/covid19-globe-tracker" | ||
rel="noopener noreferrer" | ||
target="_BLANK" | ||
style={{ color: "#ffffff", textDecoration: "none" }} | ||
> | ||
More Information | ||
</a> | ||
</div> | ||
) : null} | ||
</div> | ||
</React.Fragment> | ||
); | ||
} | ||
|
||
function Counter() { | ||
const [total, setTotal] = useState(globalData.totalCount); | ||
const [counter, setCounter] = useState(0); | ||
useEffect(() => { | ||
setTimeout(() => null, 5000); | ||
}, []); | ||
useEffect(() => { | ||
if (counter != total) { | ||
if (total - counter <= 1000) setCounter(counter + 1); | ||
else if (counter < 10000) setCounter(counter + 1000); | ||
else setCounter(counter + 500); | ||
} | ||
}, [counter]); | ||
|
||
function numberWithCommas(x: number) { | ||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | ||
} | ||
|
||
return <p>{numberWithCommas(counter)}</p>; | ||
} |
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,9 @@ | ||
export const GLOBE_IMAGE_URL = | ||
"//cdn.jsdelivr.net/npm/three-globe/example/img/earth-dark.jpg"; | ||
export const BACKGROUND_IMAGE_URL = | ||
"//cdn.jsdelivr.net/npm/three-globe/example/img/night-sky.png"; | ||
export const GEOJSON_URL = | ||
"https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson"; | ||
export const CASES_API = "https://covid3d-backend.now.sh"; | ||
|
||
export const FLAG_ENDPOINT = "https://corona.lmao.ninja/assets/img/flags"; |
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,24 @@ | ||
import React from "react"; | ||
import { useEffect, useState } from "react"; | ||
|
||
interface CounterProps { | ||
count: number; | ||
} | ||
|
||
export function Counter({ count }: CounterProps) { | ||
const [counter, setCounter] = useState(0); | ||
|
||
useEffect(() => { | ||
if (counter != count) { | ||
if (count - counter <= 1000) setCounter(counter + 1); | ||
else if (counter < 10000) setCounter(counter + 1000); | ||
else setCounter(counter + 10000); | ||
} | ||
}, [counter]); | ||
|
||
function numberWithCommas(x: number) { | ||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | ||
} | ||
|
||
return <>{numberWithCommas(counter)}</>; | ||
} |
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,11 @@ | ||
export interface Countries { | ||
[country: string]: { | ||
[date: string]: Country; | ||
}; | ||
} | ||
|
||
export interface Country { | ||
confirmed: number; | ||
recoveries: number; | ||
deaths: number; | ||
} |
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,8 @@ | ||
export class GlobalCounts { | ||
static totalConfirmed: number = 0; | ||
static totalDeaths: number = 0; | ||
static totalRecoveries: number = 0; | ||
static totalActive: number = 0; | ||
static set: boolean; | ||
private constructor() {} | ||
} |
Oops, something went wrong.