graph-cases.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import React from 'react';
  2. import format from 'date-fns/format';
  3. import { LineChart, XAxis, YAxis, Line, CartesianGrid } from 'recharts';
  4. import { lighten } from 'polished';
  5. import { Countries, CountryCases, Data } from '../types';
  6. import { getCases } from '../utils/get-cases';
  7. import { processCases } from '../utils/regression';
  8. const margin = {
  9. top: 0,
  10. right: 0,
  11. bottom: 0,
  12. left: 0,
  13. };
  14. const dateTickFormatter = (date: Date): string => {
  15. return format(new Date(date), 'LLL do'); // 'Do MMM');
  16. };
  17. type Props = {
  18. countries: Countries;
  19. };
  20. const GraphCases: React.FC<Props> = ({ countries }) => {
  21. const [showCumulative, setCumulative] = React.useState<boolean>(true);
  22. const countryCases = React.useMemo<CountryCases>(
  23. () =>
  24. countries.map(({ country, rawData }) => ({
  25. country,
  26. dataSource: getCases(rawData),
  27. })),
  28. [countries],
  29. );
  30. const data = React.useMemo<Data>(() => processCases(countryCases, showCumulative), [
  31. countryCases,
  32. showCumulative,
  33. ]);
  34. if (!data.length) {
  35. return (
  36. <div>
  37. <h3>No data!</h3>
  38. </div>
  39. );
  40. }
  41. return (
  42. <div>
  43. <p>
  44. <input type="radio" onChange={(): void => setCumulative(true)} checked={showCumulative} />
  45. Cumulative
  46. <input type="radio" onChange={(): void => setCumulative(false)} checked={!showCumulative} />
  47. Daily
  48. </p>
  49. <LineChart width={640} height={480} data={data} margin={margin}>
  50. <XAxis
  51. dataKey="xValue"
  52. domain={['auto', 'auto']}
  53. tickFormatter={dateTickFormatter}
  54. type="number"
  55. />
  56. <YAxis tick yAxisId="left" domain={[50, 'auto']} />
  57. <CartesianGrid stroke="#f5f5f5" />
  58. {countries.map(({ country, color }) => (
  59. <Line
  60. key={`actual-${country}`}
  61. type="monotone"
  62. dataKey={`value.${country}`}
  63. stroke={color}
  64. yAxisId="left"
  65. dot={false}
  66. strokeWidth={2}
  67. />
  68. ))}
  69. {countries.map(({ country, color }) => (
  70. <Line
  71. key={`regression-${country}`}
  72. type="monotone"
  73. dataKey={`regression.${country}`}
  74. stroke={lighten(0.1)(color)}
  75. yAxisId="left"
  76. dot={false}
  77. />
  78. ))}
  79. </LineChart>
  80. <ul>
  81. {countries.map(({ country, color }, index) => (
  82. <li key={country} style={{ color }}>
  83. <h3>{country}</h3>
  84. <p style={{ color: 'black' }}>
  85. Source:{' '}
  86. <a href={countryCases[index].dataSource.source}>
  87. {countryCases[index].dataSource.source}
  88. </a>
  89. </p>
  90. </li>
  91. ))}
  92. </ul>
  93. </div>
  94. );
  95. };
  96. export default GraphCases;