react-use#useEffectOnce JavaScript Examples

The following examples show how to use react-use#useEffectOnce. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: main.js    From raster-playground with GNU General Public License v3.0 5 votes vote down vote up
export default function Main() {
  const [shape, onChangeShape] = useQueryParam(URL_SHAPE, StringParam);
  const [tiles, onChangeTiles] = useQueryParam(URL_TILES, StringParam);
  const [colors, onChangeColors] = useQueryParam(URL_COLORS, StringParam);
  const [opacity, onChangeOpacity] = useQueryParam(URL_OPACITY, StringParam);
  const [theme, setTheme] = useCookie('theme-color');

  useEffectOnce(() => {
    if (!theme) themeToggler(THEME_DEFAULT, setTheme);
    else themeToggler(theme, setTheme);
  }, [theme]);

  useEffect(() => {
    if (!shape) {
      onChangeShape(SHAPE_URL_DEFAULT, URL_UPDATE_PUSH);
    }
  }, [shape, onChangeShape]);

  useEffect(() => {
    if (!tiles) {
      onChangeTiles(TILES_URL_DEFAULT, URL_UPDATE_PUSH);
    }
  }, [tiles, onChangeTiles]);

  useEffect(() => {
    if (!colors) {
      onChangeColors(COLORS_DEFAULT, URL_UPDATE_PUSH);
    }
  }, [colors, onChangeColors]);

  useEffect(() => {
    if (!opacity) {
      onChangeOpacity(OPACITY_DEFAULT, URL_UPDATE_PUSH);
    }
  }, [opacity, onChangeOpacity]);

  return (
    <>
      <MainApp theme={theme} setTheme={setTheme} />
    </>
  );
}
Example #2
Source File: navbar.js    From covid19Nepal-react with MIT License 5 votes vote down vote up
function Expand({expand, pages, setExpand}) {
  const expandElement = useRef(null);

  useEffectOnce(() => {
    anime({
      targets: expandElement.current,
      translateX: '10rem',
      easing: 'easeOutExpo',
      duration: 250,
    });
  });

  return (
    <div
      className="expand"
      ref={expandElement}
      onMouseLeave={() => {
        setExpand(false);
      }}
    >
      {pages.map((page, i) => {
        if (page.showInNavbar === true) {
          return (
            <Link
              to={page.pageLink}
              key={i}
              onClick={() => {
                setExpand(false);
              }}
            >
              <span
                {...navLinkProps(page.pageLink, page.animationDelayForNavbar)}
              >
                {page.displayName}
              </span>
            </Link>
          );
        }
        return null;
      })}

      <div className="expand-bottom fadeInUp" style={{animationDelay: '1s'}}>
        <h5>A crowdsourced initiative.</h5>
      </div>
    </div>
  );
}
Example #3
Source File: updates.js    From covid19Nepal-react with MIT License 5 votes vote down vote up
function Updates(props) {
  const [updates, setUpdates] = useState([]);

  useEffectOnce(() => {
    axios
      .get('https://api.nepalcovid19.org/updatelog/log.json')
      .then((response) => {
        setUpdates(response.data);
      })
      .catch((err) => {
        console.log(err);
      });
  });

  // reset the currentDate after rendering is complete
  // in case the currentDate was changed during addHeader
  useLayoutEffect(() => {
    currentDate = newDate;
  });

  return (
    <div className="updates">
      <div className="updates-header">
        <h2>{format(currentDate, 'd MMM')}</h2>
      </div>

      {updates
        .slice(-5)
        .reverse()
        .map(function (activity, index) {
          activity.update = activity.update.replace('\n', '<br/>');
          const activityDate = new Date(activity.timestamp * 1000);
          const addHeader = () => {
            currentDate = activityDate;

            return (
              <React.Fragment>
                {index === 0 ? (
                  <div className="update">
                    <h4>No updates yet!</h4>
                  </div>
                ) : (
                  ''
                )}
                <div className="updates-header">
                  <h2>{format(activityDate, 'd MMM')}</h2>
                </div>
              </React.Fragment>
            );
          };

          return (
            <React.Fragment key={index}>
              {activityDate.getDate() !== currentDate.getDate()
                ? addHeader()
                : ' '}
              <div key={index} className="update">
                <h5>
                  {formatDistance(
                    new Date(activity.timestamp * 1000),
                    new Date()
                  ) + ' ago'}
                </h5>
                <h4
                  dangerouslySetInnerHTML={{
                    __html: activity.update,
                  }}
                ></h4>
              </div>
            </React.Fragment>
          );
        })}
    </div>
  );
}
Example #4
Source File: App.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function App() {
  const pages = [
    {
      pageLink: '/',
      view: Home,
      displayName: 'Home',
      animationDelayForNavbar: 0.2,
      showInNavbar: true,
    },
    {
      pageLink: '/demographics',
      view: PatientDB,
      displayName: 'Demographics',
      animationDelayForNavbar: 0.3,
      showInNavbar: true,
    },
    {
      pageLink: '/deepdive',
      view: DeepDive,
      displayName: 'Deep Dive',
      animationDelayForNavbar: 0.4,
      showInNavbar: true,
    },
    {
      pageLink: '/essentials',
      view: Resources,
      displayName: 'Essentials',
      animationDelayForNavbar: 0.5,
      showInNavbar: true,
    },
    {
      pageLink: '/faq',
      view: FAQ,
      displayName: 'FAQ',
      animationDelayForNavbar: 0.6,
      showInNavbar: true,
    },
    {
      pageLink: '/state/:stateCode',
      view: State,
      displayName: 'State',
      animationDelayForNavbar: 0.7,
      showInNavbar: false,
    },
  ];

  const [darkMode, setDarkMode] = useLocalStorage('darkMode', false);
  const [isThemeSet] = useLocalStorage('isThemeSet', false);

  useEffectOnce(() => {
    if (
      window.matchMedia &&
      window.matchMedia('(prefers-color-scheme: dark)').matches &&
      !isThemeSet
    ) {
      setDarkMode(true);
    } else if (
      window.matchMedia &&
      !window.matchMedia('(prefers-color-scheme: dark)').matches &&
      !isThemeSet
    ) {
      setDarkMode(false);
    }
  });

  React.useEffect(() => {
    if (darkMode) {
      document.querySelector('body').classList.add('dark-mode');
    } else {
      document.querySelector('body').classList.remove('dark-mode');
    }
  }, [darkMode]);

  return (
    <div className="App">
      <Helmet>
        <script type="application/ld+json">
          {JSON.stringify(schemaMarkup)}
        </script>
      </Helmet>
      <Route
        render={({location}) => (
          <div className="Almighty-Router">
            <Navbar
              pages={pages}
              darkMode={darkMode}
              setDarkMode={setDarkMode}
            />
            <Switch location={location}>
              {pages.map((page, index) => {
                return (
                  <Route
                    exact
                    path={page.pageLink}
                    render={({match}) => (
                      <page.view key={match.params.stateCode || index} />
                    )}
                    key={index}
                  />
                );
              })}
              <Redirect to="/" />
            </Switch>
          </div>
        )}
      />
    </div>
  );
}
Example #5
Source File: home.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function Home(props) {
  const [states, setStates] = useState(null);
  const [stateDistrictWiseData, setStateDistrictWiseData] = useState(null);
  const [districtZones, setDistrictZones] = useState(null);
  const [stateTestData, setStateTestData] = useState(null);
  const [lastUpdated, setLastUpdated] = useState('');
  const [timeseries, setTimeseries] = useState(null);
  const [fetched, setFetched] = useState(false);
  const [regionHighlighted, setRegionHighlighted] = useState({
    state: 'Total',
  });
  const [showUpdates, setShowUpdates] = useState(false);
  const [anchor, setAnchor] = useState(null);
  const [mapOption, setMapOption] = useState('confirmed');
  const [isTimeseriesIntersecting, setIsTimeseriesIntersecting] = useState(
    false
  );

  const [lastViewedLog, setLastViewedLog] = useLocalStorage(
    'lastViewedLog',
    null
  );
  const [newUpdate, setNewUpdate] = useLocalStorage('newUpdate', false);

  const Bell = useMemo(
    () => (
      <Icon.Bell
        onClick={() => {
          setShowUpdates(!showUpdates);
          setNewUpdate(false);
        }}
      />
    ),
    [setNewUpdate, showUpdates]
  );

  const BellOff = useMemo(
    () => (
      <Icon.BellOff
        onClick={() => {
          setShowUpdates(!showUpdates);
        }}
      />
    ),
    [showUpdates]
  );

  useEffectOnce(() => {
    getStates();
  });

  useEffectOnce(() => {
    axios
      .get('https://api.nepalcovid19.org/updatelog/log.json')
      .then((response) => {
        const lastTimestamp = response.data
          .slice()
          .reverse()[0]
          .timestamp.toString();
        if (lastTimestamp !== lastViewedLog) {
          setNewUpdate(true);
          setLastViewedLog(lastTimestamp);
        }
      })
      .catch((err) => {
        console.log(err);
      });
  });

  const getStates = async () => {
    try {
      const [
        {data: statesDailyResponse},
        {data: zonesResponse},
      ] = await Promise.all([
        axios.get('https://api.nepalcovid19.org/states_daily.json'),
        axios.get(`${DATA_DIR}/zones.json`),
      ]);

      const [
        {data},
        {data: stateDistrictWiseResponse},
        {data: stateTestData},
      ] = await Promise.all([
        axios.get('https://api.nepalcovid19.org/latest_data.json'),
        axios.get('https://api.nepalcovid19.org/state-district-wise.json'),
        axios.get('https://api.nepalcovid19.org/state_test_data.json'),
      ]);

      setStates(data.statewise);
      setDistrictZones(parseDistrictZones(zonesResponse.zones));

      const ts = parseStateTimeseries(statesDailyResponse);
      ts['TT'] = preprocessTimeseries(data.cases_time_series);
      // Testing data timeseries
      const testTs = parseStateTestTimeseries(stateTestData.states_tested_data);
      testTs['TT'] = parseTotalTestTimeseries(data.tested);
      // Merge
      const tsMerged = mergeTimeseries(ts, testTs);
      setTimeseries(tsMerged);

      setLastUpdated(data.statewise[0].lastupdatedtime);

      const testData = [...stateTestData.states_tested_data].reverse();
      const totalTest = data.tested[data.tested.length - 1];
      testData.push({
        updatedon: totalTest.updatetimestamp.split(' ')[0],
        totaltested: totalTest.totalsamplestested,
        source: totalTest.source,
        state: 'Total',
      });
      setStateTestData(testData);

      setStateDistrictWiseData(stateDistrictWiseResponse);
      setFetched(true);
    } catch (err) {
      console.log(err);
    }
  };

  const onHighlightState = useCallback((state) => {
    if (!state) return setRegionHighlighted(null);
    setRegionHighlighted({state: state.state});
  }, []);

  const onHighlightDistrict = useCallback((district, state) => {
    if (!state && !district) return setRegionHighlighted(null);
    setRegionHighlighted({district, state: state.state});
  }, []);

  const options = {
    rootMargin: '0px 0px 0px 0px',
  };

  return (
    <React.Fragment>
      <div className="Home">
        <Helmet>
          <title>Coronavirus Outbreak in Nepal - nepalcovid19.org</title>
          <meta
            name="title"
            content="Coronavirus Outbreak in Nepal: Latest Map and Case Count"
          />
        </Helmet>

        <div className="home-left">
          <div className="header fadeInUp" style={{animationDelay: '1s'}}>
            {/* <LanguageSwitcher />*/}
            {fetched && <Search districtZones={districtZones} />}

            <div className="actions">
              <h5>
                {isNaN(Date.parse(formatDate(lastUpdated)))
                  ? ''
                  : formatDateAbsolute(lastUpdated)}
              </h5>
              {fetched && !showUpdates && (
                <div className="bell-icon">
                  {fetched && Bell}
                  {newUpdate && <div className="indicator"></div>}
                </div>
              )}
              {fetched && showUpdates && BellOff}
            </div>
          </div>

          {showUpdates && <Updates />}

          {states && <Level data={states[0]} />}
          {timeseries && <Minigraph timeseries={timeseries['TT']} />}
          {stateDistrictWiseData && (
            <Table
              states={states}
              summary={false}
              districts={stateDistrictWiseData}
              zones={districtZones}
              regionHighlighted={regionHighlighted}
              setRegionHighlighted={setRegionHighlighted}
              onHighlightState={onHighlightState}
              onHighlightDistrict={onHighlightDistrict}
            />
          )}
        </div>

        <div className="home-right">
          <React.Fragment>
            {fetched && (
              <MapExplorer
                mapName={'Nepal'}
                states={states}
                districts={stateDistrictWiseData}
                zones={districtZones}
                stateTestData={stateTestData}
                regionHighlighted={regionHighlighted}
                setRegionHighlighted={setRegionHighlighted}
                anchor={anchor}
                setAnchor={setAnchor}
                mapOption={mapOption}
                setMapOption={setMapOption}
              />
            )}

            <Observer
              options={options}
              onChange={({isIntersecting}) =>
                setIsTimeseriesIntersecting(isIntersecting)
              }
            >
              <div>
                {timeseries && (
                  <TimeSeriesExplorer
                    timeseries={
                      timeseries[
                        STATE_CODES_REVERSE[regionHighlighted?.state] || 'TT'
                      ]
                    }
                    activeStateCode={
                      STATE_CODES_REVERSE[regionHighlighted?.state] || 'TT'
                    }
                    onHighlightState={onHighlightState}
                    states={states}
                    anchor={anchor}
                    setAnchor={setAnchor}
                    isIntersecting={isTimeseriesIntersecting}
                  />
                )}
              </div>
            </Observer>
          </React.Fragment>
        </div>
      </div>
      {fetched && <Footer />}
    </React.Fragment>
  );
}
Example #6
Source File: level.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function Level(props) {
  const [data, setData] = useState(props.data);
  const {t} = useTranslation();

  useEffectOnce(() => {
    setData({
      active: +props.data.active,
      confirmed: +props.data.confirmed,
      recovered: +props.data.recovered,
      deaths: +props.data.deaths,
      deltaconfirmed: +props.data.deltaconfirmed,
      deltadeaths: +props.data.deltadeaths,
      deltarecovered: +props.data.deltarecovered,
    });
  });

  return (
    <div className="Level">
      <div
        className="level-item is-cherry fadeInUp"
        style={{animationDelay: '1s'}}
      >
        <h5>{t('Confirmed')}</h5>
        <h4>
          [
          {isNaN(data.deltaconfirmed)
            ? ''
            : data.deltaconfirmed > 0
            ? '+' + formatNumber(data.deltaconfirmed)
            : '+0'}
          ]
        </h4>
        <h1>{formatNumber(data.confirmed)} </h1>
      </div>

      <div
        className="level-item is-blue fadeInUp"
        style={{animationDelay: '1.1s'}}
      >
        <h5 className="heading">{t('Active')}</h5>
        <h4>&nbsp;</h4>
        <h1 className="title has-text-info">{formatNumber(data.active)}</h1>
      </div>

      <div
        className="level-item is-green fadeInUp"
        style={{animationDelay: '1.2s'}}
      >
        <h5 className="heading">{t('Recovered')}</h5>
        <h4>
          [
          {isNaN(data.deltarecovered)
            ? ''
            : data.deltarecovered > 0
            ? '+' + formatNumber(data.deltarecovered)
            : '+0'}
          ]
        </h4>
        <h1 className="title has-text-success">
          {formatNumber(data.recovered)}{' '}
        </h1>
      </div>

      <div
        className="level-item is-gray fadeInUp"
        style={{animationDelay: '1.3s'}}
      >
        <h5 className="heading">{t('Deceased')}</h5>
        <h4>
          [
          {isNaN(data.deltadeaths)
            ? ''
            : data.deltadeaths > 0
            ? '+' + formatNumber(data.deltadeaths)
            : '+0'}
          ]
        </h4>
        <h1 className="title has-text-grey">{formatNumber(data.deaths)}</h1>
      </div>
    </div>
  );
}
Example #7
Source File: row.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function Row({
  index,
  state,
  districts,
  zones,
  regionHighlighted,
  onHighlightState,
  onHighlightDistrict,
}) {
  const [sortedDistricts, setSortedDistricts] = useState(districts);
  const [showDistricts, setShowDistricts] = useState(false);
  const [sortData, setSortData] = useLocalStorage('districtSortData', {
    sortColumn: 'confirmed',
    isAscending: false,
  });

  const history = useHistory();
  const {t} = useTranslation();

  const Chevron = useMemo(
    () => (
      <span
        className={classnames(
          'dropdown',
          {rotateRightDown: showDistricts},
          {rotateDownRight: !showDistricts}
        )}
      >
        <Icon.ChevronDown />
      </span>
    ),
    [showDistricts]
  );

  const _onHighlightState = useCallback(
    (state) => {
      if (!equal(state.state, regionHighlighted?.state)) {
        onHighlightState(state);
      }
    },
    [onHighlightState, regionHighlighted]
  );

  const doSort = useCallback(
    (sortData) => {
      const sorted = {};
      Object.keys(sortedDistricts)
        .sort((district1, district2) => {
          if (sortData.sortColumn !== 'district') {
            return sortData.isAscending
              ? parseInt(sortedDistricts[district1][sortData.sortColumn]) -
                  parseInt(sortedDistricts[district2][sortData.sortColumn])
              : parseInt(sortedDistricts[district2][sortData.sortColumn]) -
                  parseInt(sortedDistricts[district1][sortData.sortColumn]);
          } else {
            return sortData.isAscending
              ? district1.localeCompare(district2)
              : district2.localeCompare(district1);
          }
        })
        .forEach((key) => {
          sorted[key] = sortedDistricts[key];
        });
      setSortedDistricts(sorted);
    },
    [sortedDistricts]
  );

  const handleSort = useCallback(
    (statistic) => {
      const newSortData = {
        isAscending: !sortData.isAscending,
        sortColumn: statistic,
      };
      doSort(newSortData);
      setSortData(Object.assign({}, sortData, newSortData));
    },
    [doSort, setSortData, sortData]
  );

  useEffectOnce(() => {
    if (state.statecode !== 'TT') doSort(sortData);
  });

  return (
    <React.Fragment>
      <tr
        className={classnames(
          'state',
          {'is-total': state.statecode === 'TT'},
          {'is-highlighted': regionHighlighted?.state === state.state},
          {'is-odd': index % 2 === 0}
        )}
        onMouseEnter={() => _onHighlightState(state)}
        onClick={
          state.statecode !== 'TT'
            ? () => {
                setShowDistricts(!showDistricts);
              }
            : null
        }
      >
        <td>
          <div className="title-chevron">
            {state.statecode !== 'TT' && Chevron}
            <span className="title-icon">
              {t(state.state)}

              <span
                data-tip={[t(`${state.statenotes}`)]}
                data-event="touchstart mouseover"
                data-event-off="mouseleave"
                onClick={(e) => e.stopPropagation()}
              >
                {state.statenotes && <Icon.Info />}
              </span>
            </span>
          </div>
        </td>

        {STATE_ROW_STATISTICS.map((statistic, index) => (
          <StateCell key={index} state={state} statistic={statistic} />
        ))}
      </tr>

      {showDistricts && (
        <React.Fragment>
          <tr className="is-spacer">
            <td colSpan={5}>
              <p />
            </td>
          </tr>

          <tr className={'state-last-update'}>
            <td colSpan={3} style={{paddingBottom: 0}}>
              <p className="spacer"></p>
              <p>
                {isNaN(Date.parse(formatDate(state.lastupdatedtime)))
                  ? ''
                  : `${t('Last updated')} ${formatDistance(
                      new Date(formatDate(state.lastupdatedtime)),
                      new Date()
                    )} ${t('ago')}`}
              </p>
              {sortedDistricts?.Unknown && (
                <div className="disclaimer">
                  <Icon.AlertCircle />
                  {t('District-wise numbers are under reconciliation')}
                </div>
              )}
            </td>
            <td
              align="center"
              className="state-page-link"
              colSpan={2}
              onClick={() => {
                history.push(`state/${state.statecode}`);
              }}
            >{`View ${t(state.state)}'s Page`}</td>
          </tr>

          <tr className={classnames('district-heading')}>
            <td onClick={() => handleSort('district')}>
              <div className="heading-content">
                <abbr title="District">{t('District')}</abbr>
                <div
                  style={{
                    display:
                      sortData.sortColumn === 'district' ? 'initial' : 'none',
                  }}
                >
                  {sortData.isAscending ? (
                    <div className="arrow-up" />
                  ) : (
                    <div className="arrow-down" />
                  )}
                </div>
              </div>
            </td>

            {DISTRICT_ROW_STATISTICS.map((statistic, index) => (
              <DistrictHeaderCell
                key={index}
                handleSort={handleSort}
                statistic={statistic}
                sortData={sortData}
              />
            ))}
          </tr>
        </React.Fragment>
      )}

      {showDistricts &&
        Object.keys(sortedDistricts).map((district, index) => (
          <DistrictRow
            key={district}
            state={state}
            district={district}
            districts={districts}
            zone={zones[district]}
            sortedDistricts={sortedDistricts}
            regionHighlighted={regionHighlighted}
            onHighlightDistrict={onHighlightDistrict}
          />
        ))}

      {showDistricts && (
        <tr className="is-spacer">
          <td colSpan={5}>
            <p />
            <ReactTooltip
              id="district"
              place="right"
              type="dark"
              effect="solid"
              multiline={true}
              scrollHide={true}
              globalEventOff="click"
            />
          </td>
        </tr>
      )}
    </React.Fragment>
  );
}
Example #8
Source File: state.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function State(props) {
  const stateCode = useParams().stateCode.toUpperCase();
  const stateName = STATE_CODES[stateCode];

  const [allStateData, setAllStateData] = useState({});
  const [fetched, setFetched] = useState(false);
  const [districtZones, setDistrictZones] = useState(null);
  const [timeseries, setTimeseries] = useState({});
  const [stateData, setStateData] = useState(null);
  const [testData, setTestData] = useState({});
  const [sources, setSources] = useState({});
  const [districtData, setDistrictData] = useState({});
  const [mapOption, setMapOption] = useState('confirmed');
  const [mapSwitcher, {width}] = useMeasure();
  const [showAllDistricts, setShowAllDistricts] = useState(false);
  const [regionHighlighted, setRegionHighlighted] = useState({
    state: stateName,
  });

  useEffectOnce(() => {
    getState(stateCode);
  });

  const getState = async (code) => {
    try {
      const [
        {data: dataResponse},
        {data: stateDistrictWiseResponse},
        {data: statesDailyResponse},
        {data: stateTestResponse},
        {data: sourcesResponse},
        {data: zonesResponse},
      ] = await Promise.all([
        axios.get('https://api.nepalcovid19.org/latest_data.json'),
        axios.get('https://api.nepalcovid19.org/state-district-wise.json'),
        axios.get('https://api.nepalcovid19.org/states_daily.json'),
        axios.get('https://api.nepalcovid19.org/state_test_data.json'),
        axios.get('https://api.nepalcovid19.org/sources_list.json'),
        axios.get(`${DATA_DIR}/zones.json`),
      ]);
      const name = STATE_CODES[code];

      const states = dataResponse.statewise;
      setAllStateData(states.filter((state) => state.statecode !== code));
      setStateData([states.find((s) => s.statecode === code)]);
      // Timeseries
      const ts = parseStateTimeseries(statesDailyResponse)[code];
      const testTs = parseStateTestTimeseries(
        stateTestResponse.states_tested_data
      )[code];
      // Merge
      const tsMerged = mergeTimeseries({[code]: ts}, {[code]: testTs});
      setTimeseries(tsMerged[code]);
      // District data
      setDistrictData({
        [name]: stateDistrictWiseResponse[name],
      });
      const sourceList = sourcesResponse.sources_list;
      setSources(sourceList.filter((state) => state.statecode === code));

      const statesTests = stateTestResponse.states_tested_data;
      setTestData(
        statesTests.filter(
          (obj) => obj.state === name && obj.totaltested !== ''
        )
      );

      setDistrictZones(parseDistrictZones(zonesResponse.zones, stateName));

      setFetched(true);
      anime({
        targets: '.highlight',
        duration: 200,
        delay: 3000,
        translateX:
          mapOption === 'confirmed'
            ? `${width * 0}px`
            : mapOption === 'active'
            ? `${width * 0.25}px`
            : mapOption === 'recovered'
            ? `${width * 0.5}px`
            : mapOption === 'deceased'
            ? `${width * 0.75}px`
            : '0px',
        easing: 'spring(1, 80, 90, 10)',
        opacity: 1,
      });
    } catch (err) {
      console.log(err);
    }
  };

  const testObjLast = testData[testData.length - 1];
  const population = STATE_POPULATIONS[stateName];

  function toggleShowAllDistricts() {
    setShowAllDistricts(!showAllDistricts);
  }

  const getGridRowCount = () => {
    const gridColumnCount = window.innerWidth >= 540 ? 3 : 2;
    const districtCount =
      (districtData[stateName] &&
        Object.keys(districtData[stateName].districtData).length) ||
      0;
    const gridRowCount = Math.ceil(districtCount / gridColumnCount);
    return gridRowCount;
  };
  const gridRowCount = getGridRowCount();

  if (!stateName) {
    return <Redirect to="/" />;
  } else {
    return (
      <React.Fragment>
        <Helmet>
          <title>
            Coronavirus Outbreak in {STATE_CODES[stateCode]} - nepalcovid19.org
          </title>
          <meta
            name="title"
            content={`Coronavirus Outbreak in ${STATE_CODES[stateCode]}: Latest Map and Case Count`}
          />
        </Helmet>

        <div className="State">
          <div className="state-left">
            <Breadcrumbs
              stateName={stateName}
              stateCode={stateCode}
              fetched={fetched}
              allStateData={allStateData}
            />

            <div className="header">
              <div
                className="header-left fadeInUp"
                style={{animationDelay: '0.3s'}}
              >
                <h1>{stateName}</h1>
                <h5>
                  Last Updated on{' '}
                  {stateData && Object.keys(stateData[0]).length
                    ? formatDateAbsolute(stateData[0].lastupdatedtime)
                    : ''}
                </h5>
              </div>

              <div
                className="header-right fadeInUp"
                style={{animationDelay: '0.5s'}}
              >
                <h5>Tested</h5>
                <h2>{formatNumber(testObjLast?.totaltested)}</h2>
                <h5 className="timestamp">
                  {!isNaN(
                    parse(testObjLast?.updatedon, 'dd/MM/yyyy', new Date())
                  )
                    ? `As of ${format(
                        parse(testObjLast?.updatedon, 'dd/MM/yyyy', new Date()),
                        'dd MMM'
                      )}`
                    : ''}
                </h5>
                <h5>
                  {'per '}
                  {testObjLast?.totaltested && (
                    <a href={testObjLast.source} target="_noblank">
                      source
                    </a>
                  )}
                </h5>
              </div>
            </div>

            {fetched && (
              <div className="map-switcher" ref={mapSwitcher}>
                <div
                  className={`highlight ${mapOption}`}
                  style={{
                    transform: `translateX(${width * 0}px)`,
                    opacity: 0,
                  }}
                ></div>
                <div
                  className="clickable"
                  onClick={() => {
                    setMapOption('confirmed');
                    anime({
                      targets: '.highlight',
                      translateX: `${width * 0}px`,
                      easing: 'spring(1, 80, 90, 10)',
                    });
                  }}
                ></div>
                <div
                  className="clickable"
                  onClick={() => {
                    setMapOption('active');
                    anime({
                      targets: '.highlight',
                      translateX: `${width * 0.25}px`,
                      easing: 'spring(1, 80, 90, 10)',
                    });
                  }}
                ></div>
                <div
                  className="clickable"
                  onClick={() => {
                    setMapOption('recovered');
                    anime({
                      targets: '.highlight',
                      translateX: `${width * 0.5}px`,
                      easing: 'spring(1, 80, 90, 10)',
                    });
                  }}
                ></div>
                <div
                  className="clickable"
                  onClick={() => {
                    setMapOption('deceased');
                    anime({
                      targets: '.highlight',
                      translateX: `${width * 0.75}px`,
                      easing: 'spring(1, 80, 90, 10)',
                    });
                  }}
                ></div>
              </div>
            )}

            {fetched && <Level data={stateData[0]} />}
            {fetched && <Minigraph timeseries={timeseries} />}
            {fetched && (
              <MapExplorer
                mapName={stateName}
                states={stateData}
                districts={districtData}
                zones={districtZones}
                stateTestData={testData}
                regionHighlighted={regionHighlighted}
                setRegionHighlighted={setRegionHighlighted}
                mapOption={mapOption}
                isCountryLoaded={false}
              />
            )}

            {fetched && (
              <div className="meta-secondary">
                <div className="alert">
                  <Icon.AlertCircle />
                  <div className="alert-right">
                    Awaiting district details for{' '}
                    {districtData[stateName]?.districtData['Unknown']
                      ?.confirmed || '0'}{' '}
                    cases
                  </div>
                </div>
                <div className="alert">
                  <Icon.Compass />
                  <div className="alert-right">
                    Data collected from sources{' '}
                    {sources.length > 0
                      ? Object.keys(sources[0]).map((key, index) => {
                          if (key.match('source') && sources[0][key] !== '') {
                            const num = key.match(/\d+/);
                            return (
                              <React.Fragment key={index}>
                                {num > 1 ? ',' : ''}
                                <a href={sources[0][key]}>{num}</a>
                              </React.Fragment>
                            );
                          }
                          return null;
                        })
                      : ''}
                  </div>
                </div>
              </div>
            )}

            {fetched && (
              <StateMeta
                stateData={stateData[0]}
                lastTestObject={testObjLast}
                population={population}
                lastSevenDaysData={timeseries.slice(-7)}
                totalData={allStateData.filter(
                  (state) => state.statecode === 'TT'
                )}
              />
            )}
          </div>

          <div className="state-right">
            {fetched && (
              <React.Fragment>
                <div
                  className="district-bar"
                  style={!showAllDistricts ? {display: 'flex'} : {}}
                >
                  <div
                    className="district-bar-left fadeInUp"
                    style={{animationDelay: '0.6s'}}
                  >
                    <h2 className={mapOption}>Top districts</h2>
                    <div
                      className={`districts ${
                        showAllDistricts ? 'is-grid' : ''
                      }`}
                      style={
                        showAllDistricts
                          ? {gridTemplateRows: `repeat(${gridRowCount}, 2rem)`}
                          : {}
                      }
                    >
                      {districtData[stateName]
                        ? Object.keys(districtData[stateName].districtData)
                            .filter((d) => d !== 'Unknown')
                            .sort((a, b) => {
                              const districtB =
                                districtData[stateName].districtData[b];
                              const districtA =
                                districtData[stateName].districtData[a];
                              return (
                                districtB[mapOption] - districtA[mapOption]
                              );
                            })
                            .slice(0, showAllDistricts ? undefined : 5)
                            .map((district, index) => {
                              const cases =
                                districtData[stateName].districtData[district];
                              return (
                                <div key={index} className="district">
                                  <h2>{cases[mapOption]}</h2>
                                  <h5>{district}</h5>
                                  {mapOption !== 'active' && (
                                    <div className="delta">
                                      <Icon.ArrowUp className={mapOption} />
                                      <h6 className={mapOption}>
                                        {cases.delta[mapOption]}
                                      </h6>
                                    </div>
                                  )}
                                </div>
                              );
                            })
                        : ''}
                    </div>
                    {districtData[stateName] &&
                      Object.keys(districtData[stateName].districtData).length >
                        5 && (
                        <button
                          className="button"
                          onClick={toggleShowAllDistricts}
                        >
                          {showAllDistricts ? `View less` : `View all`}
                        </button>
                      )}
                  </div>
                  <div className="district-bar-right">
                    {(mapOption === 'confirmed' ||
                      mapOption === 'deceased') && (
                      <div
                        className="happy-sign fadeInUp"
                        style={{animationDelay: '0.6s'}}
                      >
                        {timeseries
                          .slice(-5)
                          .every((day) => day[`daily${mapOption}`] === 0) && (
                          <div
                            className={`alert ${
                              mapOption === 'confirmed' ? 'is-green' : ''
                            }`}
                          >
                            <Icon.Smile />
                            <div className="alert-right">
                              No new {mapOption} cases in the past five days
                            </div>
                          </div>
                        )}
                      </div>
                    )}
                    {
                      <DeltaBarGraph
                        timeseries={timeseries.slice(-5)}
                        arrayKey={`daily${mapOption}`}
                      />
                    }
                  </div>
                </div>

                {false && (
                  <Link to="/essentials">
                    <div
                      className="to-essentials fadeInUp"
                      style={{animationDelay: '0.9s'}}
                    >
                      <h2>Go to essentials</h2>
                      <Icon.ArrowRightCircle />
                    </div>
                  </Link>
                )}

                <TimeSeriesExplorer timeseries={timeseries} />
              </React.Fragment>
            )}
          </div>

          <div className="state-left">
            <div className="Clusters fadeInUp" style={{animationDelay: '0.8s'}}>
              <h1>Network of Transmission</h1>
              <Clusters stateCode={stateCode} />
            </div>
          </div>

          <div className="state-right"></div>
        </div>
        <Footer />
      </React.Fragment>
    );
  }
}
Example #9
Source File: table.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function Table({
  states,
  districts,
  zones,
  regionHighlighted,
  onHighlightState,
  onHighlightDistrict,
}) {
  const [sortData, setSortData] = useLocalStorage('sortData', {
    sortColumn: 'confirmed',
    isAscending: false,
  });
  const {t} = useTranslation();

  const [sortedStates, setSortedStates] = useState(
    states.filter((state) => state.statecode !== 'TT')
  );

  const FineprintTop = useMemo(
    () => (
      <React.Fragment>
        <h5
          className="table-fineprint fadeInUp"
          style={{animationDelay: '1.5s'}}
        >
          {t('Compiled from State Govt. numbers')},{' '}
          <Link to="/faq" style={{color: '#6c757d'}}>
            {t('know more')}!
          </Link>
        </h5>
        <h5
          className="table-fineprint fadeInUp"
          style={{animationDelay: '1.5s'}}
        >
          District zones as published by Govt, source
        </h5>
      </React.Fragment>
    ),
    [t]
  );

  const FineprintBottom = useMemo(
    () => (
      <h5 className="table-fineprint fadeInUp" style={{animationDelay: '1s'}}>
        {states.slice(1).filter((s) => s && s.confirmed > 0).length} Province
        Affected
      </h5>
    ),
    [states]
  );

  const doSort = useCallback(
    (sortData) => {
      const newSortedStates = [...sortedStates].sort((x, y) => {
        if (sortData.sortColumn !== 'state') {
          return sortData.isAscending
            ? parseInt(x[sortData.sortColumn]) -
                parseInt(y[sortData.sortColumn])
            : parseInt(y[sortData.sortColumn]) -
                parseInt(x[sortData.sortColumn]);
        } else {
          return sortData.isAscending
            ? x[sortData.sortColumn].localeCompare(y[sortData.sortColumn])
            : y[sortData.sortColumn].localeCompare(x[sortData.sortColumn]);
        }
      });
      setSortedStates(newSortedStates);
    },
    [sortedStates]
  );

  const handleSort = useCallback(
    (statistic) => {
      const newSortData = {
        isAscending: !sortData.isAscending,
        sortColumn: statistic,
      };
      doSort(newSortData);
      setSortData(Object.assign({}, sortData, newSortData));
    },
    [doSort, setSortData, sortData]
  );

  useEffectOnce(() => {
    doSort(sortData);
  });

  if (states.length > 0) {
    return (
      <React.Fragment>
        <ReactTooltip
          place="right"
          type="dark"
          effect="solid"
          multiline={true}
          globalEventOff="click"
        />

        {FineprintTop}

        <table className="table fadeInUp" style={{animationDelay: '1.8s'}}>
          <thead>
            <tr>
              <th className="state-heading" onClick={() => handleSort('state')}>
                <div className="heading-content">
                  <abbr title="State">{t('Province')}</abbr>
                  <div
                    style={{
                      display:
                        sortData.sortColumn === 'state' ? 'initial' : 'none',
                    }}
                  >
                    <div
                      className={classnames(
                        {'arrow-up': sortData.isAscending},
                        {'arrow-down': !sortData.isAscending}
                      )}
                    />
                  </div>
                </div>
              </th>
              {STATE_ROW_STATISTICS.map((statistic, index) => (
                <StateHeaderCell
                  key={index}
                  handleSort={handleSort}
                  sortData={sortData}
                  statistic={statistic}
                />
              ))}
            </tr>
          </thead>

          {states && (
            <tbody>
              {sortedStates.map((state, index) => {
                if (state.confirmed > 0 && state.statecode !== 'TT') {
                  return (
                    <Row
                      key={state.statecode}
                      state={state}
                      districts={districts[state.state]?.districtData}
                      zones={zones[state.state]}
                      regionHighlighted={
                        equal(regionHighlighted?.state, state.state)
                          ? regionHighlighted
                          : null
                      }
                      onHighlightState={onHighlightState}
                      onHighlightDistrict={onHighlightDistrict}
                    />
                  );
                }
                return null;
              })}
            </tbody>
          )}

          {states && (
            <tbody>
              <Row
                key={0}
                state={states[0]}
                onHighlightState={onHighlightState}
              />
            </tbody>
          )}
        </table>
        {states && FineprintBottom}
      </React.Fragment>
    );
  } else {
    return <div style={{height: '50rem'}}></div>;
  }
}