Skip to content

DashboardTab hand-rolls its own formatTimeAgo instead of the date-fns formatter IssuesTab already uses #894

Description

@Jagadeeshftw

Description

Two sibling components in the same feature area each implement their own "time ago" formatter instead of sharing one. src/features/maintainers/components/issues/IssuesTab.tsx uses the already-installed date-fns package ("date-fns": "3.6.0" in package.json):

const formatTimeAgo = useCallback((dateString: string | null): string => {
  if (!dateString) { ... return 'Unknown' }
  try {
    const date = new Date(dateString)
    if (isNaN(date.getTime())) { ... return 'Unknown' }
    return formatDistanceToNow(date, { addSuffix: true })
  } catch (err) { ... return 'Unknown' }
}, [])

src/features/maintainers/components/dashboard/DashboardTab.tsx, in the same features/maintainers area, instead hand-rolls the same concept with its own bucket math:

const formatTimeAgo = useCallback((date: Date): string => {
  const timeMs = date.getTime()
  if (isNaN(timeMs)) { return 'unknown time' }
  const now = new Date()
  const diffMs = now.getTime() - timeMs
  const diffMins = Math.floor(diffMs / 60000)
  const diffHours = Math.floor(diffMs / 3600000)
  const diffDays = Math.floor(diffMs / 86400000)
  const diffMonths = Math.floor(diffDays / 30)

  if (diffMins < 1) return 'just now'
  if (diffMins < 60) return `${diffMins} minute${diffMins !== 1 ? 's' : ''} ago`
  if (diffHours < 24) return `${diffHours} hour${diffHours !== 1 ? 's' : ''} ago`
  if (diffDays < 30) return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`
  return `${diffMonths} month${diffMonths !== 1 ? 's' : ''} ago`
}, [])

Besides the duplication, DashboardTab's version has no "years ago" bucket at all — diffMonths just keeps growing past 12 (e.g. an 800-day-old activity item renders as "26 months ago" instead of the far more readable "2 years ago" that date-fns's formatDistanceToNow would produce, and which IssuesTab.tsx already gets for free). It also takes a Date while IssuesTab.tsx's version takes a string | null and has its own Unknown/error-handling conventions — two incompatible signatures for the same conceptual helper in the same feature.

Requirements

  • Replace DashboardTab.tsx's hand-rolled formatTimeAgo with date-fns's formatDistanceToNow (matching IssuesTab.tsx's usage), or extract one shared helper both files import.
  • Preserve the existing invalid-date fallback behavior ('unknown time' / 'Unknown' — pick one consistent string) in the consolidated version.

Suggested execution

  1. Fork the repo and create a branch: git checkout -b fix/dashboardtab-formattimeago-datefns
  2. Extract a single shared formatTimeAgo helper (e.g. under src/shared/utils/) built on date-fns's formatDistanceToNow, accepting the same input shape both call sites need.
  3. Update DashboardTab.tsx and IssuesTab.tsx to both import the shared helper, removing their local copies.
  4. Add a test asserting an ~800-day-old timestamp renders using a "years" bucket rather than an ever-growing months count.

Example commit message

fix: replace DashboardTab's hand-rolled formatTimeAgo with the shared date-fns formatter

Acceptance criteria

  • DashboardTab.tsx and IssuesTab.tsx share one formatTimeAgo implementation built on date-fns.
  • A multi-year-old timestamp renders with a "years ago" style output instead of a large raw month count.
  • A test covers the shared helper's bucket boundaries.

Security notes

None; this is a duplication/correctness issue with no security surface.

Guidelines

  • Minimum 95% test coverage
  • Timeframe: 96 hours

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions