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