diff options
| author | eug-vs <eug-vs@keemail.me> | 2020-10-09 21:46:45 +0300 | 
|---|---|---|
| committer | eug-vs <eug-vs@keemail.me> | 2020-10-09 21:46:45 +0300 | 
| commit | 31900353b6ea3e4570c15d1c1585685b4413d6d9 (patch) | |
| tree | 79883fb938ca4452361147cc18f0bc866067e303 | |
| parent | 7605be6c77393ed98e179c27f3bc3915afb95f5c (diff) | |
| download | which-ui-31900353b6ea3e4570c15d1c1585685b4413d6d9.tar.gz | |
feat: toggle between compact and full date format
| -rw-r--r-- | src/components/DateString/DateString.tsx | 27 | ||||
| -rw-r--r-- | src/components/DateString/compactDateString.ts | 34 | 
2 files changed, 57 insertions, 4 deletions
diff --git a/src/components/DateString/DateString.tsx b/src/components/DateString/DateString.tsx index e31b52e..3f2ceb2 100644 --- a/src/components/DateString/DateString.tsx +++ b/src/components/DateString/DateString.tsx @@ -1,9 +1,18 @@ -import React from 'react'; +import React, { useState, useMemo, useCallback } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import compactDateString from './compactDateString';  interface PropTypes {    value: Date | string;  } +const useStyles = makeStyles({ +  root: { +    display: 'block', +    cursor: 'pointer' +  } +}); +  const DATE_FORMAT = {    month: 'long',    day: 'numeric', @@ -13,10 +22,20 @@ const DATE_FORMAT = {  };  const DateString: React.FC<PropTypes> = ({ value }) => { -  const date = new Date(value); -  const formatted = date.toLocaleString('default', DATE_FORMAT); +  const [isCompact, setIsCompact] = useState<boolean>(true); +  const classes = useStyles(); + +  const toggleScompact = useCallback(() => setIsCompact(v => !v), [setIsCompact]); + +  const date = useMemo(() => new Date(value), [value]); +  const formatted = useMemo(() => date.toLocaleString('default', DATE_FORMAT), [date]); +  const compact = useMemo(() => compactDateString(date), [date]); -  return <>{formatted}</>; +  return ( +    <div className={classes.root} onClick={toggleScompact}> +      {isCompact ? compact : formatted} +    </div> +  );  };  export default DateString; diff --git a/src/components/DateString/compactDateString.ts b/src/components/DateString/compactDateString.ts new file mode 100644 index 0000000..dffd912 --- /dev/null +++ b/src/components/DateString/compactDateString.ts @@ -0,0 +1,34 @@ +const metrics = [ +  { name: 'minute', ratio: 60 }, +  { name: 'hour', ratio: 60 }, +  { name: 'day', ratio: 24 }, +  { name: 'week', ratio: 7 }, +  { name: 'month', ratio: 4 }, +  { name: 'year', ratio: 12 } +]; + +const PRECISION = 0.75; + +const resolve = (value: number, metricIndex = 0): string => { +  // Recursively divide value until it's ready to be presented as a string +  const metric = metrics[metricIndex]; +  const nextMetric = metrics[metricIndex + 1]; +  const newValue = value / metric.ratio; + +  if (newValue < nextMetric.ratio * PRECISION) { +    const rounded = Math.round(newValue); +    const isPlural = rounded > 1; +    const count = isPlural ? rounded : 'a'; +    const ending = isPlural ? 's' : ''; +    return `${count} ${metric.name}${ending} ago`; +  } +  return resolve(newValue, metricIndex + 1); +}; + +const compactDateString = (date: Date): string => { +  const now = new Date(); +  const diff = (now.valueOf() - date.valueOf()) / 1000; +  return resolve(diff); +}; + +export default compactDateString;  |