date-fns#formatDistance JavaScript Examples

The following examples show how to use date-fns#formatDistance. 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: AppNewsUpdate.js    From course-manager with MIT License 6 votes vote down vote up
function NewsItem({ news }) {
  const { image, title, description, postedAt } = news;

  return (
    <Stack direction="row" alignItems="center" spacing={2}>
      <Box
        component="img"
        alt={title}
        src={image}
        sx={{ width: 48, height: 48, borderRadius: 1.5 }}
      />
      <Box sx={{ minWidth: 240 }}>
        <Link to="#" color="inherit" underline="hover" component={RouterLink}>
          <Typography variant="subtitle2" noWrap>
            {title}
          </Typography>
        </Link>
        <Typography variant="body2" sx={{ color: 'text.secondary' }} noWrap>
          {description}
        </Typography>
      </Box>
      <Typography variant="caption" sx={{ pr: 3, flexShrink: 0, color: 'text.secondary' }}>
        {formatDistance(postedAt, new Date())}
      </Typography>
    </Stack>
  );
}
Example #2
Source File: LastUpdatedIndicator.js    From livecovid.in-webapp with MIT License 6 votes vote down vote up
LastUpdatedIndicator = (props) => (
  <div className="live-indicator-wrapper">
    <div className="live-indicator" />
    <div className="last-updated-main">
      {' '}
      Updated
      {' '}
      {formatDistance(
        new Date(Date.parse(`${props.lastUpdated.slice(0, 19)}+05:30`)),
        new Date(),
      )}
      {' '}
      ago
    </div>
  </div>
)
Example #3
Source File: Item.jsx    From killed-by-microsoft with MIT License 6 votes vote down vote up
getYears() {
    const { dateClose, dateOpen } = this.props;
    const duration = formatDistance(parseISO(dateClose), parseISO(dateOpen));

    if (this.isPast()) {
      return ` It was ${duration} old.`;
    }
    return ` It will be ${duration} old.`;
  }
Example #4
Source File: scheduledtasks.js    From jellyfin-web-jmp with GNU General Public License v2.0 6 votes vote down vote up
function getTaskProgressHtml(task) {
        let html = '';
        if (task.State === 'Idle') {
            if (task.LastExecutionResult) {
                const endtime = Date.parse(task.LastExecutionResult.EndTimeUtc);
                const starttime = Date.parse(task.LastExecutionResult.StartTimeUtc);
                html += globalize.translate('LabelScheduledTaskLastRan', formatDistanceToNow(endtime, localeWithSuffix),
                    formatDistance(starttime, endtime, { locale: getLocale() }));
                if (task.LastExecutionResult.Status === 'Failed') {
                    html += " <span style='color:#FF0000;'>(" + globalize.translate('LabelFailed') + ')</span>';
                } else if (task.LastExecutionResult.Status === 'Cancelled') {
                    html += " <span style='color:#0026FF;'>(" + globalize.translate('LabelCancelled') + ')</span>';
                } else if (task.LastExecutionResult.Status === 'Aborted') {
                    html += " <span style='color:#FF0000;'>" + globalize.translate('LabelAbortedByServerShutdown') + '</span>';
                }
            }
        } else if (task.State === 'Running') {
            const progress = (task.CurrentProgressPercentage || 0).toFixed(1);
            html += '<div style="display:flex;align-items:center;">';
            html += '<div class="taskProgressOuter" title="' + progress + '%" style="flex-grow:1;">';
            html += '<div class="taskProgressInner" style="width:' + progress + '%;">';
            html += '</div>';
            html += '</div>';
            html += "<span style='color:#00a4dc;margin-left:5px;'>" + progress + '%</span>';
            html += '</div>';
        } else {
            html += "<span style='color:#FF0000;'>" + globalize.translate('LabelStopping') + '</span>';
        }
        return html;
    }
Example #5
Source File: scheduledtasks.js    From veso-web with GNU General Public License v2.0 6 votes vote down vote up
function getTaskProgressHtml(task) {
        let html = '';
        if (task.State === 'Idle') {
            if (task.LastExecutionResult) {
                const endtime = Date.parse(task.LastExecutionResult.EndTimeUtc);
                const starttime = Date.parse(task.LastExecutionResult.StartTimeUtc);
                html += globalize.translate('LabelScheduledTaskLastRan', formatDistanceToNow(endtime, localeWithSuffix),
                    formatDistance(starttime, endtime, { locale: getLocale() }));
                if (task.LastExecutionResult.Status === 'Failed') {
                    html += " <span style='color:#FF0000;'>(" + globalize.translate('LabelFailed') + ')</span>';
                } else if (task.LastExecutionResult.Status === 'Cancelled') {
                    html += " <span style='color:#0026FF;'>(" + globalize.translate('LabelCancelled') + ')</span>';
                } else if (task.LastExecutionResult.Status === 'Aborted') {
                    html += " <span style='color:#FF0000;'>" + globalize.translate('LabelAbortedByServerShutdown') + '</span>';
                }
            }
        } else if (task.State === 'Running') {
            const progress = (task.CurrentProgressPercentage || 0).toFixed(1);
            html += '<div style="display:flex;align-items:center;">';
            html += '<div class="taskProgressOuter" title="' + progress + '%" style="flex-grow:1;">';
            html += '<div class="taskProgressInner" style="width:' + progress + '%;">';
            html += '</div>';
            html += '</div>';
            html += "<span style='color:#d61e30;margin-left:5px;'>" + progress + '%</span>';
            html += '</div>';
        } else {
            html += "<span style='color:#FF0000;'>" + globalize.translate('LabelStopping') + '</span>';
        }
        return html;
    }
Example #6
Source File: Timestamp.jsx    From ResoBin with MIT License 6 votes vote down vote up
Timestamp = ({ time }) => {
  return time ? (
    <Tooltip title={format(new Date(time), 'dd.MM.yyyy')}>
      <DateTitle>
        {formatDistance(new Date(time), new Date(), {
          addSuffix: true,
        })}
      </DateTitle>
    </Tooltip>
  ) : null
}
Example #7
Source File: init.client.js    From audiobookshelf with GNU General Public License v3.0 5 votes vote down vote up
Vue.prototype.$dateDistanceFromNow = (unixms) => {
  if (!unixms) return ''
  return formatDistance(unixms, Date.now(), { addSuffix: true })
}
Example #8
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 #9
Source File: Updates.js    From covid19india-react with MIT License 5 votes vote down vote up
function Updates({updates}) {
  const {t} = useTranslation();

  useLayoutEffect(() => {
    currentDate = newDate;
  });

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

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

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

          return (
            <Fragment key={index}>
              {activityDate.getDate() !== currentDate.getDate()
                ? addHeader()
                : ' '}
              <div key={index} className="update">
                <h5>
                  {capitalize(
                    formatDistance(
                      new Date(activity.timestamp * 1000),
                      new Date()
                    )
                  ) + ` ${t('ago')}`}
                </h5>
                <h4
                  dangerouslySetInnerHTML={{
                    __html: activity.update,
                  }}
                ></h4>
              </div>
            </Fragment>
          );
        })}
      <div className="updates-footer">
        <a
          href="https://t.me/covid19indiaorg_updates"
          target="_blank"
          className="telegram"
          rel="noopener noreferrer"
        >
          <h4>
            {t('Get updates on Telegram')}
            <CrossReferenceIcon />
          </h4>
        </a>
      </div>
    </div>
  );
}
Example #10
Source File: commonFunctions.js    From covid19india-react with MIT License 5 votes vote down vote up
formatLastUpdated = (unformattedDate) => {
  getLocale();
  return formatDistance(new Date(unformattedDate), new Date(), {
    locale: locale,
  });
}
Example #11
Source File: comments.js    From instagram with MIT License 5 votes vote down vote up
export default function Comments({ docId, comments: allComments, posted, commentInput }) {
  const [comments, setComments] = useState(allComments);
  const [commentsSlice, setCommentsSlice] = useState(3);

  const showNextComments = () => {
    setCommentsSlice(commentsSlice + 3);
  };

  return (
    <>
      <div className="p-4 pt-1 pb-4">
        {comments.slice(0, commentsSlice).map((item) => (
          <p key={`${item.comment}-${item.displayName}`} className="mb-1">
            <Link to={`/p/${item.displayName}`}>
              <span className="mr-1 font-bold">{item.displayName}</span>
            </Link>
            <span>{item.comment}</span>
          </p>
        ))}
        {comments.length >= 3 && commentsSlice < comments.length && (
          <button
            className="text-sm text-gray-base mb-1 cursor-pointer focus:outline-none"
            type="button"
            onClick={showNextComments}
            onKeyDown={(event) => {
              if (event.key === 'Enter') {
                showNextComments();
              }
            }}
          >
            View more comments
          </button>
        )}
        <p className="text-gray-base uppercase text-xs mt-2">
          {formatDistance(posted, new Date())} ago
        </p>
      </div>
      <AddComment
        docId={docId}
        comments={comments}
        setComments={setComments}
        commentInput={commentInput}
      />
    </>
  );
}
Example #12
Source File: ago.js    From awesome-react-starter with MIT License 5 votes vote down vote up
ago = (date) => {
  try {
    return formatDistance(new Date(date), new Date());
  } catch (err) {
    return '';
  }
}
Example #13
Source File: CovidApp.js    From covid-19-tracker with MIT License 4 votes vote down vote up
render() {
    const { classes, setDarkMode, isDarkMode } = this.props;
    const { mapData, isLoading, data, districtLevel, expanded, updates } =
      this.state;

    if (isLoading) {
      return (
        <div className={classes.loadingIcon}>
          <Lottie options={defaultOptions} height={500} width={500} />
        </div>
      );
    }
    let displayUpdates;
    try {
      displayUpdates = updates
        .slice(-5)
        .reverse()
        .map(({ update, timestamp }, i) => {
          update = update.replace('\n', '<br/>');
          return (
            <div className={classes.updateBox} key={i}>
              <h5 className={classes.updateHeading}>
                {`${formatDistance(
                  new Date(timestamp * 1000),
                  new Date()
                )} ago`}
              </h5>
              <h4
                className={classes.updateText}
                dangerouslySetInnerHTML={{
                  __html: update,
                }}
              ></h4>
            </div>
          );
        });
    } catch (err) {}

    return (
      <>
        <div className={classes.header}>
          <h1 className={classes.heading}>
            <span>Covid-19</span> India Trend
          </h1>
          <div className={classes.btnBox}>
            <FontAwesomeIcon
              icon={faSyncAlt}
              className={classes.button}
              onClick={this.fetchData}
            />
          </div>
          <div className={classes.lastUpdatedTime}>
            Last Updated:{' '}
            {this.formatDate(this.state.todayData.lastupdatedtime)}
          </div>
          <div className={classes.updates}>
            <div className={classes.notification}>
              {expanded ? (
                <FontAwesomeIcon
                  icon={faBellSlash}
                  onClick={this.handleNotification}
                />
              ) : (
                <div className={classes.notificationBell}>
                  <FontAwesomeIcon
                    icon={faBell}
                    onClick={this.handleNotification}
                  />
                </div>
              )}
            </div>
            {expanded && <div className={classes.update}>{displayUpdates}</div>}
          </div>
          <div className="darkModeButton">
            <label className="switch">
              <input
                type="checkbox"
                onChange={setDarkMode}
                checked={isDarkMode}
              />
              <span className="slider round"></span>
            </label>
          </div>
        </div>
        <div>
          <Overview
            isDarkMode={isDarkMode}
            data={this.state.todayData}
            loadingStatus={this.loadingStatus}
          />
        </div>
        <div className={classes.content}>
          <div className={classes.contentArea}>
            <div className={classes.mapArea}>
              <MapSection
                data={data}
                mapData={mapData}
                isDarkMode={isDarkMode}
              />
            </div>
          </div>
          <div className={classes.chartArea}>
            <div className={classes.chartRes}>
              <Charts
                data={this.state.casesTimeline}
                isLoading={this.state.isLoading}
              />
            </div>
            <div className={classes.tinyChartArea}>
              <div className={classes.tinyChart}>
                <div
                  className={classes.tinych}
                  style={{ background: 'rgba(249, 52, 94,.1)' }}
                >
                  <h3 style={{ color: colors.red }}>confirmed</h3>
                  <Barchart
                    data={this.state.casesTimeline}
                    isLoading={this.state.isLoading}
                    dataKey="totalconfirmed"
                    stroke={colors.red}
                  />
                </div>
              </div>
              <div className={classes.tinyChart}>
                <div
                  className={classes.tinych}
                  style={{ background: 'rgba(250, 100, 0,.1)' }}
                >
                  <h3 style={{ color: colors.orange }}>active</h3>
                  <Barchart
                    data={this.state.casesTimeline}
                    isLoading={this.state.isLoading}
                    dataKey="totalactive"
                    stroke={colors.orange}
                  />
                </div>
              </div>
              <div className={classes.tinyChart}>
                <div
                  className={classes.tinych}
                  style={{ background: 'rgba(28, 177, 66,.1)' }}
                >
                  <h3 style={{ color: colors.green }}>Recovered</h3>
                  <Barchart
                    data={this.state.casesTimeline}
                    isLoading={this.state.isLoading}
                    dataKey="totalrecovered"
                    stroke={colors.green}
                  />
                </div>
              </div>
              <div className={classes.tinyChart}>
                <div
                  className={classes.tinych}
                  style={{ background: 'rgba(98, 54, 255,.1)' }}
                >
                  <h3 style={{ color: colors.purple }}>Deceased</h3>
                  <Barchart
                    data={this.state.casesTimeline}
                    isLoading={this.state.isLoading}
                    dataKey="totaldeceased"
                    stroke={colors.purple}
                  />
                </div>
              </div>
            </div>
          </div>
          <div className={classes.tableContainer}>
            <h2 className={classes.tableHeading}>
              State/UT Wise Data (Sortable){' '}
            </h2>
            <DisplayTable
              tableData={data}
              districtLevel={districtLevel}
              isDarkMode={isDarkMode}
            />
          </div>
        </div>
        <Footer />
      </>
    );
  }
Example #14
Source File: mapexplorer.js    From covid19Nepal-react with MIT License 4 votes vote down vote up
function MapExplorer({
  mapName,
  states,
  districts,
  zones,
  stateTestData,
  regionHighlighted,
  setRegionHighlighted,
  anchor,
  setAnchor,
  mapOption,
  setMapOption,
  isCountryLoaded = true,
}) {
  const {t} = useTranslation();
  const [currentMap, setCurrentMap] = useState({
    name: mapName,
    stat: MAP_STATISTICS.TOTAL,
    view:
      MAP_META[mapName].mapType === MAP_TYPES.COUNTRY
        ? MAP_VIEWS.STATES
        : MAP_VIEWS.DISTRICTS,
  });
  const currentMapMeta = MAP_META[currentMap.name];

  const [statistic, currentMapData] = useMemo(() => {
    let currentMapData = {};
    let statistic = {};
    if (currentMap.stat === MAP_STATISTICS.ZONE) {
      const dataTypes = ['Red', 'Orange', 'Green'];
      statistic = dataTypes.reduce((acc, dtype) => {
        acc[dtype] = 0;
        return acc;
      }, {});
      if (currentMapMeta.mapType === MAP_TYPES.COUNTRY) {
        currentMapData = Object.keys(zones).reduce((acc1, state) => {
          acc1[state] = Object.keys(zones[state]).reduce((acc2, district) => {
            const zone = zones[state][district].zone;
            if (zone) {
              acc2[district] = zone;
              statistic[zone] += 1;
            }
            return acc2;
          }, {});
          return acc1;
        }, {});
      } else if (currentMapMeta.mapType === MAP_TYPES.STATE) {
        const state = currentMap.name;
        currentMapData[state] = Object.keys(zones[state]).reduce(
          (acc, district) => {
            const zone = zones[state][district].zone;
            if (zone) {
              acc[district] = zone;
              statistic[zone] += 1;
            }
            return acc;
          },
          {}
        );
      }
    } else {
      const dataTypes = ['confirmed', 'active', 'recovered', 'deceased'];
      statistic = dataTypes.reduce((acc, dtype) => {
        acc[dtype] = {total: 0, max: 0};
        return acc;
      }, {});
      if (currentMapMeta.mapType === MAP_TYPES.COUNTRY) {
        currentMapData = states.reduce((acc, state) => {
          acc[state.state] = {};
          dataTypes.forEach((dtype) => {
            let typeCount = parseInt(
              state[dtype !== 'deceased' ? dtype : 'deaths']
            );
            if (currentMap.stat === MAP_STATISTICS.PER_MILLION)
              typeCount = (1e6 * typeCount) / STATE_POPULATIONS[state.state];
            if (state.state !== 'Total') {
              statistic[dtype].total += typeCount;
              if (typeCount > statistic[dtype].max) {
                statistic[dtype].max = typeCount;
              }
            }
            acc[state.state][dtype] = typeCount;
          });
          return acc;
        }, {});
      } else if (currentMapMeta.mapType === MAP_TYPES.STATE) {
        const districtWiseData = (
          districts[currentMap.name] || {districtData: {}}
        ).districtData;
        currentMapData[currentMap.name] = Object.keys(districtWiseData).reduce(
          (acc, district) => {
            acc[district] = {};
            dataTypes.forEach((dtype) => {
              const typeCount = parseInt(districtWiseData[district][dtype]);
              statistic[dtype].total += typeCount;
              if (typeCount > statistic[dtype].max) {
                statistic[dtype].max = typeCount;
              }
              acc[district][dtype] = typeCount;
            });
            return acc;
          },
          {}
        );
        currentMapData[currentMap.name].Total = states.find(
          (state) => currentMap.name === state.state
        );
      }
    }
    return [statistic, currentMapData];
  }, [
    currentMap.name,
    currentMap.stat,
    currentMapMeta.mapType,
    districts,
    zones,
    states,
  ]);

  const [hoveredRegion, panelRegion] = useMemo(() => {
    if (!regionHighlighted.district) {
      const state = getRegionFromState(
        states.find((state) => regionHighlighted.state === state.state)
      );
      return [state, state];
    } else {
      const stateDistrictObj = districts[regionHighlighted.state] || {
        districtData: {},
      };
      const districtData = stateDistrictObj.districtData[
        regionHighlighted.district
      ] || {
        confirmed: 0,
        active: 0,
        recovered: 0,
        deaths: 0,
      };
      const district = getRegionFromDistrict(
        districtData,
        regionHighlighted.district
      );
      let state = getRegionFromState(
        states.find((state) => state.state === regionHighlighted.state)
      );
      district.district = regionHighlighted.district;
      district.state = state.state;
      if (currentMapMeta.mapType === MAP_TYPES.COUNTRY)
        state = states.find((state) => state.state === 'Total');
      return [district, state];
    }
  }, [states, districts, currentMapMeta.mapType, regionHighlighted]);

  useEffect(() => {
    if (regionHighlighted === undefined || regionHighlighted === null) return;

    if ('district' in regionHighlighted) {
      if (
        currentMap.name !== regionHighlighted.state &&
        !(
          currentMapMeta.mapType === MAP_TYPES.COUNTRY &&
          currentMap.view === MAP_VIEWS.DISTRICTS
        )
      ) {
        const state = regionHighlighted.state;
        const newMapMeta = MAP_META[state];
        if (!newMapMeta) {
          return;
        }
        setCurrentMap({
          name: state,
          view: MAP_VIEWS.DISTRICTS,
          stat:
            currentMap.stat === MAP_STATISTICS.PER_MILLION
              ? MAP_STATISTICS.TOTAL
              : currentMap.stat,
        });
      }
    } else if (isCountryLoaded && currentMapMeta.mapType === MAP_TYPES.STATE) {
      setCurrentMap({
        name: 'Nepal',
        view:
          currentMap.stat === MAP_STATISTICS.ZONE
            ? MAP_VIEWS.DISTRICTS
            : MAP_VIEWS.STATES,
        stat: currentMap.stat,
      });
    }
  }, [isCountryLoaded, regionHighlighted, currentMap, currentMapMeta.mapType]);

  const switchMapToState = useCallback(
    (state) => {
      const newMapMeta = MAP_META[state];
      if (!newMapMeta) {
        return;
      }
      if (newMapMeta.mapType === MAP_TYPES.STATE) {
        const {districtData} = districts[state] || {
          districtData: {},
        };
        const topDistrict = Object.keys(districtData)
          .filter((state) => state !== 'Unknown')
          .sort((a, b) => {
            return districtData[b].confirmed - districtData[a].confirmed;
          })[0];
        ReactDOM.unstable_batchedUpdates(() => {
          setRegionHighlighted({
            district: topDistrict,
            state: state,
          });
          setCurrentMap({
            name: state,
            view: MAP_VIEWS.DISTRICTS,
            stat:
              currentMap.stat === MAP_STATISTICS.PER_MILLION
                ? MAP_STATISTICS.TOTAL
                : currentMap.stat,
          });
        });
      } else {
        ReactDOM.unstable_batchedUpdates(() => {
          setCurrentMap({
            name: 'Nepal',
            view:
              currentMap.stat === MAP_STATISTICS.ZONE
                ? MAP_VIEWS.DISTRICTS
                : MAP_VIEWS.STATES,
            stat: currentMap.stat,
          });
          setRegionHighlighted({
            state: 'Total',
          });
        });
      }
    },
    [currentMap.stat, districts, setRegionHighlighted]
  );

  const testObj = useMemo(
    () =>
      stateTestData.find(
        (obj) => obj.state === panelRegion.state && obj.totaltested !== ''
      ),
    [stateTestData, panelRegion]
  );

  let hoveredRegionCount;
  let hoveredRegionZone;
  if (currentMap.stat !== MAP_STATISTICS.ZONE) {
    const data =
      hoveredRegion.district && currentMapData[hoveredRegion.state]
        ? currentMapData[hoveredRegion.state][hoveredRegion.district]
        : hoveredRegion.state !== currentMap.name
        ? currentMapData[hoveredRegion.state]
        : currentMapData[hoveredRegion.state].Total;
    hoveredRegionCount = data
      ? currentMap.stat === MAP_STATISTICS.PER_MILLION
        ? Number(parseFloat(data[mapOption]).toFixed(2))
        : data[mapOption]
      : 0;
  } else {
    hoveredRegionZone =
      zones[hoveredRegion.state] &&
      zones[hoveredRegion.state][hoveredRegion.district]
        ? zones[hoveredRegion.state][hoveredRegion.district].zone
        : '';
  }

  return (
    <div
      className={`MapExplorer fadeInUp ${
        anchor === 'mapexplorer' ? 'stickied' : ''
      }`}
      style={{
        animationDelay: '1.5s',
        display: anchor === 'timeseries' ? 'none' : '',
      }}
    >
      {window.innerWidth > 769 && (
        <div
          className={`anchor ${anchor === 'mapexplorer' ? 'stickied' : ''}`}
          onClick={() => {
            setAnchor(anchor === 'mapexplorer' ? null : 'mapexplorer');
          }}
        >
          <Icon.Anchor />
        </div>
      )}
      <div className="header">
        <h1>
          {t(currentMap.name)} {t('Map')}
        </h1>
        <h6>
          {window.innerWidth <= 769 ? t('Tap') : t('Hover')} over a{' '}
          {currentMapMeta.mapType === MAP_TYPES.COUNTRY
            ? t('state/UT')
            : t('district')}{' '}
          {t('for more details')}
        </h6>
      </div>

      <div className="map-stats">
        <div
          className={`stats fadeInUp ${
            mapOption === 'confirmed' ? 'focused' : ''
          }`}
          style={{animationDelay: '2s'}}
          onClick={() => setMapOption('confirmed')}
        >
          <h5>{window.innerWidth <= 769 ? t('Cnfmd') : t('Confirmed')}</h5>
          <div className="stats-bottom">
            <h1>{formatNumber(panelRegion.confirmed)}</h1>
            <h6>{`+${formatNumber(panelRegion.deltaconfirmed)}`}</h6>
          </div>
        </div>

        <div
          className={`stats is-blue fadeInUp ${
            mapOption === 'active' ? 'focused' : ''
          }`}
          style={{animationDelay: '2.1s'}}
          onClick={() => setMapOption('active')}
        >
          <h5>{window.innerWidth <= 769 ? t('Actv') : t('Active')}</h5>
          <div className="stats-bottom">
            <h1>{formatNumber(panelRegion.active)}</h1>
            <h6>{` `}</h6>
          </div>
        </div>

        <div
          className={`stats is-green fadeInUp ${
            mapOption === 'recovered' ? 'focused' : ''
          }`}
          style={{animationDelay: '2.2s'}}
          onClick={() => setMapOption('recovered')}
        >
          <h5>{window.innerWidth <= 769 ? t('Rcvrd') : t('Recovered')}</h5>
          <div className="stats-bottom">
            <h1>{formatNumber(panelRegion.recovered)}</h1>
            <h6>{`+${formatNumber(panelRegion.deltarecovered)}`}</h6>
          </div>
        </div>

        <div
          className={`stats is-gray fadeInUp ${
            mapOption === 'deceased' ? 'focused' : ''
          }`}
          style={{animationDelay: '2.3s'}}
          onClick={() => setMapOption('deceased')}
        >
          <h5>{window.innerWidth <= 769 ? t('Dcsd') : t('Deceased')}</h5>
          <div className="stats-bottom">
            <h1>{formatNumber(panelRegion.deaths)}</h1>
            <h6>{`+${formatNumber(panelRegion.deltadeaths)}`}</h6>
          </div>
        </div>

        <div
          className="stats is-purple tested fadeInUp"
          style={{animationDelay: '2.4s'}}
        >
          <h5>{t('Tested')}</h5>
          <div className="stats-bottom">
            <h1>{formatNumber(testObj?.totaltested)}</h1>
          </div>
          <h6 className="timestamp">
            {!isNaN(parse(testObj?.updatedon, 'dd/MM/yyyy', new Date()))
              ? `${t('As of')} ${format(
                  parse(testObj?.updatedon, 'dd/MM/yyyy', new Date()),
                  'dd MMM'
                )}`
              : ''}
          </h6>
          {testObj?.totaltested?.length > 1 && (
            <a href={testObj.source} target="_noblank">
              <Icon.Link />
            </a>
          )}
          {panelRegion.state === 'Total' ? testedToolTip : ''}
        </div>
      </div>

      <div className="meta fadeInUp" style={{animationDelay: '2.4s'}}>
        <h2
          className={`${
            currentMap.stat !== MAP_STATISTICS.ZONE
              ? mapOption !== 'confirmed'
                ? mapOption
                : ''
              : hoveredRegionZone
          }`}
        >
          {hoveredRegion.district
            ? t(hoveredRegion.district)
            : t(hoveredRegion.state)}
        </h2>

        {currentMapMeta.mapType !== MAP_TYPES.STATE &&
          panelRegion.lastupdatedtime && (
            <div className="last-update">
              <h6>{t('Last updated')}</h6>
              <h3>
                {isNaN(Date.parse(formatDate(panelRegion.lastupdatedtime)))
                  ? ''
                  : formatDistance(
                      new Date(formatDate(panelRegion.lastupdatedtime)),
                      new Date()
                    ) +
                    ' ' +
                    t('ago')}
              </h3>
            </div>
          )}

        {currentMapMeta.mapType === MAP_TYPES.STATE ? (
          <Link to={`state/${STATE_CODES_REVERSE[panelRegion.state]}`}>
            <div className="button state-page-button">
              <abbr>{t('Visit state page')}</abbr>
              <Icon.ArrowRightCircle />
            </div>
          </Link>
        ) : null}

        {currentMap.stat !== MAP_STATISTICS.ZONE &&
        (currentMapMeta.mapType === MAP_TYPES.STATE ||
          (currentMapMeta.mapType === MAP_TYPES.COUNTRY &&
            currentMap.stat !== MAP_STATISTICS.TOTAL)) ? (
          <h1
            className={`district ${mapOption !== 'confirmed' ? mapOption : ''}`}
          >
            {hoveredRegionCount}
            <br />
            <span>
              {mapOption}{' '}
              {currentMap.stat === MAP_STATISTICS.PER_MILLION
                ? ` ${t('per million')}`
                : ''}
            </span>
          </h1>
        ) : null}

        {currentMapMeta.mapType === MAP_TYPES.STATE ? (
          <div
            className="button back-button"
            onClick={() => switchMapToState('Nepal')}
          >
            Back
          </div>
        ) : null}

        {currentMapMeta.mapType === MAP_TYPES.STATE &&
        currentMapData.Unknown &&
        currentMapData.Unknown[mapOption] > 0 ? (
          <h4 className="unknown">
            {t('Districts unknown for')} {currentMapData.Unknown[mapOption]}{' '}
            {t('people')}
          </h4>
        ) : null}
      </div>

      <div>
        {mapOption && (
          <ChoroplethMap
            statistic={statistic}
            currentMap={currentMap}
            mapData={currentMapData}
            regionHighlighted={regionHighlighted}
            setRegionHighlighted={setRegionHighlighted}
            changeMap={switchMapToState}
            isCountryLoaded={isCountryLoaded}
            mapOption={mapOption}
          />
        )}
      </div>

      <div className="tabs-map">
        <div
          className={`tab ${
            currentMap.stat === MAP_STATISTICS.TOTAL ? 'focused' : ''
          }`}
          onClick={() => {
            setCurrentMap({
              name: currentMap.name,
              view:
                currentMapMeta.mapType === MAP_TYPES.COUNTRY
                  ? MAP_VIEWS.STATES
                  : MAP_VIEWS.DISTRICTS,
              stat: MAP_STATISTICS.TOTAL,
            });
            if (currentMapMeta.mapType === MAP_TYPES.COUNTRY)
              setRegionHighlighted({
                state: regionHighlighted.state,
              });
          }}
        >
          <h4>{t('Total Cases')}</h4>
        </div>
        {isCountryLoaded && (
          <div
            className={`tab ${
              currentMap.stat === MAP_STATISTICS.PER_MILLION ? 'focused' : ''
            }`}
            onClick={() => {
              if (currentMapMeta.mapType === MAP_TYPES.STATE) return;
              setCurrentMap({
                name: currentMap.name,
                view: MAP_VIEWS.STATES,
                stat: MAP_STATISTICS.PER_MILLION,
              });
              setRegionHighlighted({
                state: regionHighlighted.state,
              });
            }}
          >
            <h4>
              {t('Cases per million')}
              <sup>&dagger;</sup>
            </h4>
          </div>
        )}
        {/* <div
          className={`tab ${
            currentMap.stat === MAP_STATISTICS.ZONE ? 'focused' : ''
          }`}
          onClick={() => {
            setCurrentMap({
              name: currentMap.name,
              view: MAP_VIEWS.DISTRICTS,
              stat: MAP_STATISTICS.ZONE,
            });
            if (currentMapMeta.mapType === MAP_TYPES.COUNTRY)
              setRegionHighlighted({
                state: 'Total',
              });
          }}
        >
          <h4>Zones</h4>
        </div> */}
      </div>

      <h6 className="footnote table-fineprint">
        &dagger; {t('Based on 2019 population projection') + '('}
        <a
          href="https://www.citypopulation.de/php/nepal-admin.php"
          target="_noblank"
          style={{color: '#6c757d'}}
        >
          {t('report')}
        </a>
        )
      </h6>
    </div>
  );
}
Example #15
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>
  );
}