# All files / src/components/Graphs useCountryCovidData.ts

0% Statements 0/63
0% Branches 0/71
0% Functions 0/13
0% Lines 0/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129

     import { CountryStats, DayData, CountryData, countryData, Countries, DayStatistics, CountriesResult } from './types';
    import { useFetch } from '@cutting/react-abortable-fetch';
    import dayjs from 'dayjs';
    import { uniqBy } from '@cutting/util';
    import utc from 'dayjs/plugin/utc';
    import urlJoin from 'url-join';
    import assert from 'assert-ts';
    import { useEffect, useState } from 'react';

    dayjs.extend(utc);

    // documenter.getpostman.com/view/2568274/SzS8rjbe?version=latest
    const baseUrl = 'https://covidapi.info/api/v1/country';

    export const transform = (results: CountryStats, country: CountryData): DayData[] => {
      const data = results.result.map(({ date, deaths, ...rest }, i) => {
        return {
          x: dayjs.utc(date).format(),
          y: deaths,
          index: i,
          country,
          deaths,
          ...rest,
        };
      });

      const result = data.map((d, i) => {
        return {
          ...d,
          delta: i === 0 ? 0 : d.confirmed - data[i - 1].confirmed,
          deltaDeaths: i === 0 ? 0 : d.y - data[i - 1].y,
        };
      });

      return (result as unknown) as DayData[];
    };

    const DefaultStartDate = '2020-03-01'; //;dayjs().subtract(45, 'day').format('YYYY-MM-DD');

    export interface CountryDataProps {
      startDate: string;
    }

    export const BreakPoint = 14;

    export const useCountryCovidData = (
      { startDate }: CountryDataProps = { startDate: DefaultStartDate },
    ): { data: CountriesResult | undefined } => {
      const [finalData, setFinalData] = useState<CountriesResult>();

      const urls = Object.keys(countryData)
        .filter((c) => c !== 'SCO')
        .map((c) => urlJoin(baseUrl, c.toUpperCase(), 'timeseries', startDate, dayjs().format('YYYY-MM-DD')));

      const { data } = useFetch<CountriesResult, CountryStats>(urls, {
        accumulator: (acc, current, { request }) => {
          current.result = uniqBy(current.result, (a) => a.date);

          assert(typeof request === 'string', `unexpected request in accumulation context ${request}`);

          const country = request.split('/')[6] as Countries;

          const countryDetails = countryData[country];

          acc[country] = {
            data: transform(current, countryDetails).filter((d, i) => {
              const diff = dayjs().diff(dayjs(d.x), 'd');
              return diff <= 10 || i % BreakPoint === 0;
            }),
            color: countryDetails.color,
            name: countryDetails.longName,
          };

          return acc;
        },
        initialState: {} as CountriesResult,
        executeOnMount: true,
      });

      const { data: scotsData } = useFetch<
        CountriesResult,
        { result: { records: { Deaths: number; CumulativeCases: number; Date: string }[] } }
      >(
        'https://www.opendata.nhs.scot/api/3/action/datastore_search?resource_id=287fc645-4352-4477-9c8c-55bc054b7e76&limit=1000&sort=Date%20desc',
        {
          fetchType: 'fetchJsonp',
          executeOnMount: true,
          initialState: {} as CountriesResult,
          accumulator: (acc, current) => {
            const scotlandStats: DayStatistics[] = [];
            for (const record of current.result.records.reverse()) {
              const rawDate = record.Date.toString();
              const date = `${rawDate.substr(0, 4)}-${rawDate.substr(4, 2)}-${rawDate.substr(6, 2)}`;

              scotlandStats.push({
                date,
                deaths: record.Deaths,
                recovered: 0,
                confirmed: record.CumulativeCases,
              });
            }

            acc.SCO = {
              data: transform({ result: scotlandStats }, countryData.SCO),
              color: countryData.SCO.color,
              name: countryData.SCO.longName,
            };

            return acc;
          },
        },
      );

      useEffect(() => {
        if (!!finalData || !scotsData?.SCO?.data?.length || !data?.GBR?.data?.length) {
          return;
        }

        const recognisedDates = data?.GBR?.data.map((x) => x.x) || [];

        scotsData.SCO.data = scotsData.SCO.data.filter((d) => recognisedDates.includes(d.x));

        setFinalData({ ...data, ...scotsData });
        // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [data?.GBR?.data?.length, scotsData?.SCO?.data?.length]);

      return { data: finalData };
    };