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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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>†</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">
† {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 |
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>
);
}