10 changed files with 471 additions and 104 deletions
@ -0,0 +1,45 @@ |
|||
import React from "react"; |
|||
import { |
|||
ResponsiveContainer, |
|||
AreaChart as AC, |
|||
CartesianGrid, |
|||
XAxis, |
|||
YAxis, |
|||
Tooltip, |
|||
Legend, |
|||
Area, |
|||
} from "recharts"; |
|||
import { ChartProps } from "../types"; |
|||
|
|||
export default function AreaChart(props: ChartProps) { |
|||
return ( |
|||
<ResponsiveContainer height={300}> |
|||
<AC |
|||
width={600} |
|||
height={300} |
|||
data={props.data.map((d) => { |
|||
return { |
|||
name: d.name, |
|||
...d.values, |
|||
}; |
|||
})} |
|||
> |
|||
{Object.keys(props.data[0].values).map((k, i) => ( |
|||
<Area |
|||
type="monotone" |
|||
key={i} |
|||
dataKey={k} |
|||
stroke="#8884d8" |
|||
fill="#8884d8" |
|||
name={k} |
|||
/> |
|||
))} |
|||
<CartesianGrid stroke="#ccc" /> |
|||
<XAxis dataKey="name" /> |
|||
<YAxis scale={props.scale ?? "auto"} /> |
|||
<Tooltip /> |
|||
<Legend verticalAlign="top" /> |
|||
</AC> |
|||
</ResponsiveContainer> |
|||
); |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
import React from "react"; |
|||
import TextField from "@mui/material/TextField"; |
|||
import AdapterDateFns from "@mui/lab/AdapterDateFns"; |
|||
import LocalizationProvider from "@mui/lab/LocalizationProvider"; |
|||
import DateRangePicker, { DateRange } from "@mui/lab/DateRangePicker"; |
|||
import Box from "@mui/material/Box"; |
|||
import { DatePickerProps } from "../types"; |
|||
|
|||
export default function DatePicker(props: DatePickerProps) { |
|||
return ( |
|||
<LocalizationProvider dateAdapter={AdapterDateFns}> |
|||
<DateRangePicker |
|||
value={props.value} |
|||
minDate={props.minDate} |
|||
maxDate={props.maxDate} |
|||
onChange={(newValue: DateRange<Date>) => { |
|||
props.setValue(newValue); |
|||
}} |
|||
startText="Kezdeti dátum" |
|||
endText="Végső dátum" |
|||
renderInput={(startProps, endProps) => ( |
|||
<> |
|||
<TextField {...startProps} /> |
|||
<Box sx={{ mx: 2 }}> - </Box> |
|||
<TextField {...endProps} /> |
|||
</> |
|||
)} |
|||
/> |
|||
</LocalizationProvider> |
|||
); |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
import React from "react"; |
|||
import AreaChart from "./AreaChart"; |
|||
import Typography from "@mui/material/Typography"; |
|||
import Grid from "@mui/material/Grid"; |
|||
import { useGetAllDataQuery } from "../services/covidDataApi"; |
|||
import { ChartData } from "../types"; |
|||
import { DateRange } from "@mui/lab/DateRangePicker"; |
|||
import DatePicker from "./DatePicker"; |
|||
|
|||
export default function Home() { |
|||
const { data, error, isLoading } = useGetAllDataQuery({}); |
|||
const [dateRange, setDateRange] = React.useState<DateRange<Date>>([ |
|||
null, |
|||
null, |
|||
]); |
|||
|
|||
let allData: ChartData[] = []; |
|||
let newInfected: ChartData[] = []; |
|||
|
|||
if (data) { |
|||
if (dateRange[0] == null && dateRange[1] == null) { |
|||
setDateRange([ |
|||
new Date(data[0].created_at), |
|||
new Date(data[data.length - 1].created_at), |
|||
]); |
|||
} |
|||
|
|||
allData = data |
|||
.map((d) => { |
|||
const date = new Date(d.created_at); |
|||
const currentInfected = d.infected - d.recovered - d.deceased; |
|||
return { |
|||
name: |
|||
date.getFullYear() + |
|||
"." + |
|||
("0" + (date.getMonth() + 1)).slice(-2) + |
|||
"." + |
|||
("0" + date.getDate()).slice(-2), |
|||
values: { |
|||
"Aktív fertőzöttek napi alakulása": currentInfected > 0 ? currentInfected : 0, |
|||
}, |
|||
}; |
|||
}) |
|||
.filter((d) => { |
|||
const ddate = new Date(d.name); |
|||
if (dateRange[0] == null || dateRange[1] == null) return true; |
|||
let endDate = new Date(dateRange[1].getTime()); |
|||
endDate.setDate(endDate.getDate() + 1); |
|||
return ddate >= dateRange[0] && ddate < endDate; |
|||
}); |
|||
|
|||
let newData = 0; |
|||
newInfected = data |
|||
.map((d) => { |
|||
const date = new Date(d.created_at); |
|||
const newActual = d.infected - newData; |
|||
newData = d.infected; |
|||
return { |
|||
name: |
|||
date.getFullYear() + |
|||
"." + |
|||
("0" + (date.getMonth() + 1)).slice(-2) + |
|||
"." + |
|||
("0" + date.getDate()).slice(-2), |
|||
values: { |
|||
"Új fertőzöttek napi alakulása": newActual > 0 ? newActual : 0, |
|||
}, |
|||
}; |
|||
}) |
|||
.filter((d) => { |
|||
const ddate = new Date(d.name); |
|||
if (dateRange[0] == null || dateRange[1] == null) return true; |
|||
let endDate = new Date(dateRange[1].getTime()); |
|||
endDate.setDate(endDate.getDate() + 1); |
|||
return ddate >= dateRange[0] && ddate < endDate; |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<> |
|||
<Typography paragraph> |
|||
Ez az oldal elsősorban a hivatalos, kormány által közölt |
|||
adatokat dolgozza fel, de nem tekinthető hivatalos |
|||
tájékoztatásnak, továbbá nem vállalunk felelősséget a kormány |
|||
által közölt adatok és információk valóságtartalmáért. Kérjük, a |
|||
hivatalos információkért látogasson el a kormány által |
|||
működtetett{" "} |
|||
<a href="https://koronavirus.gov.hu/" target="_blank"> |
|||
koronavirus.gov.hu |
|||
</a>{" "} |
|||
oldalra, illetve olvassa a nagyobb hírportálok híreit. |
|||
</Typography> |
|||
{typeof data != "undefined" ? ( |
|||
<Grid container spacing={2}> |
|||
<Grid |
|||
item |
|||
xs={12} |
|||
container |
|||
spacing={2} |
|||
justifyContent="center" |
|||
> |
|||
<Grid item> |
|||
<DatePicker |
|||
minDate={new Date(data[0].created_at)} |
|||
maxDate={ |
|||
new Date(data[data.length - 1].created_at) |
|||
} |
|||
value={dateRange} |
|||
setValue={(n: DateRange<Date>) => |
|||
setDateRange(n) |
|||
} |
|||
/> |
|||
</Grid> |
|||
</Grid> |
|||
<Grid item md={6} xs={12}> |
|||
<AreaChart |
|||
data={allData} |
|||
scale="sqrt" |
|||
/> |
|||
</Grid> |
|||
<Grid item md={6} xs={12}> |
|||
<AreaChart |
|||
data={newInfected} |
|||
scale="sqrt" |
|||
/> |
|||
</Grid> |
|||
</Grid> |
|||
) : null} |
|||
</> |
|||
); |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
import React from "react"; |
|||
import { |
|||
ResponsiveContainer, |
|||
LineChart as LC, |
|||
CartesianGrid, |
|||
XAxis, |
|||
YAxis, |
|||
Tooltip, |
|||
Legend, |
|||
Line, |
|||
} from "recharts"; |
|||
import { ChartProps } from "../types"; |
|||
|
|||
export default function LineChart(props: ChartProps) { |
|||
return ( |
|||
<ResponsiveContainer height={300}> |
|||
<LC |
|||
width={600} |
|||
height={300} |
|||
data={props.data.map((d) => { |
|||
return { |
|||
name: d.name, |
|||
...d.values, |
|||
}; |
|||
})} |
|||
> |
|||
{Object.keys(props.data[0].values).map((k, i) => ( |
|||
<Line |
|||
type="monotone" |
|||
key={i} |
|||
dataKey={k} |
|||
stroke="#8884d8" |
|||
name={k} |
|||
dot={false} |
|||
/> |
|||
))} |
|||
<CartesianGrid stroke="#ccc" /> |
|||
<XAxis dataKey="name" /> |
|||
<YAxis scale={props.scale ?? "auto"} /> |
|||
<Tooltip /> |
|||
<Legend verticalAlign="top" /> |
|||
</LC> |
|||
</ResponsiveContainer> |
|||
); |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
import React from "react"; |
|||
import { |
|||
PieChart as PC, |
|||
Pie, |
|||
Legend, |
|||
Tooltip, |
|||
ResponsiveContainer, |
|||
Cell, |
|||
} from "recharts"; |
|||
import { ChartProps } from "../types"; |
|||
|
|||
const colors = ["#82ca9d", "#8884d8"]; |
|||
|
|||
export default function PieChart(props: ChartProps) { |
|||
return ( |
|||
<ResponsiveContainer height={300}> |
|||
<PC width={600} height={300}> |
|||
<Pie |
|||
dataKey="value" |
|||
data={Object.keys( |
|||
props.data[props.data.length - 1].values |
|||
).map((k) => ({ |
|||
name: k, |
|||
value: props.data[props.data.length - 1].values[k], |
|||
}))} |
|||
innerRadius={40} |
|||
outerRadius={80} |
|||
fill="#82ca9d" |
|||
label |
|||
> |
|||
{Object.keys(props.data[props.data.length - 1].values) |
|||
.map((k) => ({ |
|||
name: k, |
|||
value: props.data[props.data.length - 1].values[k], |
|||
})) |
|||
.map((entry, index) => ( |
|||
<Cell |
|||
key={`cell-${index}`} |
|||
fill={colors[index % colors.length]} |
|||
/> |
|||
))} |
|||
</Pie> |
|||
<Tooltip /> |
|||
<Legend /> |
|||
</PC> |
|||
</ResponsiveContainer> |
|||
); |
|||
} |
|||
@ -0,0 +1,114 @@ |
|||
import React from "react"; |
|||
import Typography from "@mui/material/Typography"; |
|||
import Grid from "@mui/material/Grid"; |
|||
import { useGetAllDataQuery } from "../services/covidDataApi"; |
|||
import { ChartData } from "../types"; |
|||
import { DateRange } from "@mui/lab/DateRangePicker"; |
|||
import DatePicker from "./DatePicker"; |
|||
import LineChart from "./LineChart"; |
|||
import PieChart from "./PieChart"; |
|||
|
|||
export default function RecoveryRate() { |
|||
const { data, error, isLoading } = useGetAllDataQuery({}); |
|||
const [dateRange, setDateRange] = React.useState<DateRange<Date>>([ |
|||
null, |
|||
null, |
|||
]); |
|||
|
|||
let lineData: ChartData[] = []; |
|||
let pieData: ChartData[] = []; |
|||
|
|||
if (data) { |
|||
if (dateRange[0] == null && dateRange[1] == null) { |
|||
setDateRange([ |
|||
new Date(data[0].created_at), |
|||
new Date(data[data.length - 1].created_at), |
|||
]); |
|||
} |
|||
|
|||
lineData = data |
|||
.map((d) => { |
|||
const date = new Date(d.created_at); |
|||
return { |
|||
name: |
|||
date.getFullYear() + |
|||
"." + |
|||
("0" + (date.getMonth() + 1)).slice(-2) + |
|||
"." + |
|||
("0" + date.getDate()).slice(-2), |
|||
values: { |
|||
"Gyógyultak száma": d.recovered ?? 0, |
|||
"Elhalálozottak száma": d.deceased ?? 0, |
|||
}, |
|||
}; |
|||
}) |
|||
.filter((d) => { |
|||
const ddate = new Date(d.name); |
|||
if (dateRange[0] == null || dateRange[1] == null) return true; |
|||
let endDate = new Date(dateRange[1].getTime()); |
|||
endDate.setDate(endDate.getDate() + 1); |
|||
return ddate >= dateRange[0] && ddate < endDate; |
|||
}); |
|||
|
|||
pieData = data |
|||
.filter((n) => { |
|||
const ddate = new Date(n.created_at); |
|||
if (dateRange[0] == null || dateRange[1] == null) return true; |
|||
let endDate = new Date(dateRange[1].getTime()); |
|||
endDate.setDate(endDate.getDate() + 1); |
|||
return ddate >= dateRange[0] && ddate < endDate; |
|||
}) |
|||
.map((d) => { |
|||
const date = new Date(d.created_at); |
|||
return { |
|||
name: |
|||
date.getFullYear() + |
|||
"." + |
|||
("0" + (date.getMonth() + 1)).slice(-2) + |
|||
"." + |
|||
("0" + date.getDate()).slice(-2), |
|||
values: { |
|||
Gyógyultak: d.recovered ?? 0, |
|||
Elhalálozottak: d.deceased ?? 0, |
|||
}, |
|||
}; |
|||
}); |
|||
} |
|||
return ( |
|||
<> |
|||
<Typography paragraph> |
|||
A gyógyultak és az elhalálozottak számának alakulása |
|||
</Typography> |
|||
{typeof data != "undefined" ? ( |
|||
<Grid container spacing={2}> |
|||
<Grid |
|||
item |
|||
xs={12} |
|||
container |
|||
spacing={2} |
|||
justifyContent="center" |
|||
> |
|||
<Grid item> |
|||
<DatePicker |
|||
minDate={new Date(data[0].created_at)} |
|||
maxDate={ |
|||
new Date(data[data.length - 1].created_at) |
|||
} |
|||
value={dateRange} |
|||
setValue={(n: DateRange<Date>) => |
|||
setDateRange(n) |
|||
} |
|||
/> |
|||
</Grid> |
|||
</Grid> |
|||
<Grid item md={6} xs={12}> |
|||
<LineChart data={lineData} scale="sqrt" /> |
|||
</Grid> |
|||
<Grid item md={6} xs={12}> |
|||
<PieChart data={pieData} /> |
|||
</Grid> |
|||
</Grid> |
|||
) : null} |
|||
</> |
|||
); |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
import { DateRange } from "@mui/lab/DateRangePicker"; |
|||
import { ScaleType } from "recharts/types/util/types"; |
|||
|
|||
|
|||
export interface CovidData { |
|||
infected: number; |
|||
deceased: number; |
|||
recovered: number; |
|||
quarantined: number; |
|||
tested: number; |
|||
created_at: Date; |
|||
} |
|||
|
|||
export interface ChartData { |
|||
name: string; |
|||
values: { |
|||
[key: string]: number |
|||
}; |
|||
} |
|||
|
|||
export interface ChartProps { |
|||
data: ChartData[]; |
|||
scale?: ScaleType; |
|||
} |
|||
|
|||
export interface DatePickerProps { |
|||
minDate: Date; |
|||
maxDate: Date; |
|||
value: DateRange<Date>; |
|||
setValue: Function; |
|||
} |
|||
Loading…
Reference in new issue