Skip to content

Refactor/date fns - #1069

Open
scheidtdav wants to merge 14 commits into
devfrom
refactor/date-fns
Open

Refactor/date fns#1069
scheidtdav wants to merge 14 commits into
devfrom
refactor/date-fns

Conversation

@scheidtdav

@scheidtdav scheidtdav commented Aug 19, 2026

Copy link
Copy Markdown
Member

Type of Change

  • Dependency upgrade
  • Bug fix (non-breaking change)
  • Breaking change
    • e.g. a fixed bug or new feature that may break something else
  • New feature
  • Code quality improvements
    • e.g. refactoring, documentation, tests, tooling, ...

Implementation

Checklist

  • I gave this pull request a meaningful title
  • My pull request is targeting the dev branch
  • I have added documentation to my code
  • I have deleted code that I have commented out

Additional Information

@scheidtdav scheidtdav linked an issue Aug 19, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Improvements
    • Dates and times across device, user, profile, log, transfer, map, and range-picker views now follow the active language setting.
    • Sensor timestamps display localized relative time, including accurate handling of future dates.
    • Map popups and date pickers provide consistent localized date and time formatting.
    • Date displays now load consistently without briefly showing mismatched locale formatting.

Walkthrough

The PR replaces selected date-fns formatting with Intl.DateTimeFormat, Intl.RelativeTimeFormat, and the active i18n language across shared components and routes. Several route timestamps now render only after hydration.

Changes

Date localization

Layer / File(s) Summary
Relative-time formatter
app/lib/date.ts
Adds dateDiffToNowInWords with threshold-based localized relative-time units.
Component date formatting
app/components/device-detail/device-detail-box.tsx, app/components/map/layers/mobile/mobile-overview-layer.tsx, app/components/ui/range-picker.tsx
Uses the active i18n language for sensor ages, map popup times, and date-range display.
Route date formatting
app/components/mydevices/dt/columns.tsx, app/routes/admin.devices._index.tsx, app/routes/admin.users._index.tsx, app/routes/device.$deviceId.edit.logs.tsx, app/routes/device.$deviceId.edit.transfer.tsx, app/routes/profile.$username.tsx
Defers timestamp rendering until hydration and formats dates with the active i18n language.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🟡 Moderate · up to 5cf66

Date displays can be incorrect or inconsistent: some dates may appear one year old too early, server and browser rendering may disagree across time zones, and missing profile data may produce an invalid creation date. The PR should not merge until these bounded correctness issues are addressed or explicitly accepted.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides only the PR template and issue links, without explaining the implementation or scope of the date-fns replacement. Add a short summary of the browser-native replacements, affected date displays, hydration handling, and any remaining date-fns usage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title identifies a date-fns refactor, which matches the primary change to browser-native date handling.
Linked Issues check ✅ Passed The changes replace date-fns formatting and relative-time usage with Intl APIs and a locale-aware helper in the affected components [#1061].
Out of Scope Changes check ✅ Passed The changes remain focused on date-fns replacement, localized date rendering, relative-time formatting, and hydration-safe output.
Docstring Coverage ✅ Passed Docstring check was indeterminate for this PR — some files could not be analyzed in time. Not blocking.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/date-fns

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 65.99% 2242 / 3397
🔵 Statements 64.53% 2316 / 3589
🔵 Functions 63.21% 433 / 685
🔵 Branches 50.84% 1081 / 2126
File CoverageNo changed files found.
Generated in workflow #2909 for commit 5cf6600 by the Vitest Coverage Report Action

@scheidtdav scheidtdav linked an issue Aug 20, 2026 that may be closed by this pull request
3 tasks
@scheidtdav
scheidtdav marked this pull request as ready for review August 20, 2026 08:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b4d4e3bc-162f-46da-8926-4951b398f3c8

📥 Commits

Reviewing files that changed from the base of the PR and between 3f79a72 and 2e026c8.

📒 Files selected for processing (11)
  • app/components/device-detail/device-detail-box.tsx
  • app/components/device-detail/graph.tsx
  • app/components/map/layers/mobile/mobile-overview-layer.tsx
  • app/components/mydevices/dt/columns.tsx
  • app/components/ui/range-picker.tsx
  • app/lib/date.ts
  • app/routes/admin.devices._index.tsx
  • app/routes/admin.users._index.tsx
  • app/routes/device.$deviceId.edit.logs.tsx
  • app/routes/device.$deviceId.edit.transfer.tsx
  • app/routes/profile.$username.tsx
💤 Files with no reviewable changes (1)
  • app/components/device-detail/graph.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread app/components/ui/range-picker.tsx
Comment thread app/components/ui/range-picker.tsx
Comment thread app/lib/date.ts Outdated
@scheidtdav

Copy link
Copy Markdown
Member Author

Gotta do the code rabbit reviews still..

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ab467778-630c-4a13-a85c-18f46e3da057

📥 Commits

Reviewing files that changed from the base of the PR and between 2e026c8 and 53d1ae1.

📒 Files selected for processing (8)
  • app/components/mydevices/dt/columns.tsx
  • app/components/ui/range-picker.tsx
  • app/lib/date.ts
  • app/routes/admin.devices._index.tsx
  • app/routes/admin.users._index.tsx
  • app/routes/device.$deviceId.edit.logs.tsx
  • app/routes/device.$deviceId.edit.transfer.tsx
  • app/routes/profile.$username.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread app/routes/profile.$username.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/routes/profile.$username.tsx (1)

163-166: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard the creation date before formatting it.

When the loader returns profile: null, this expression constructs new Date('') after hydration. The formatter then receives an invalid date instead of omitting the creation date. Check profile?.user?.createdAt before calling toLocaleDateString.

Proposed fix
-								{hydrated &&
-									new Date(profile?.user?.createdAt || '').toLocaleDateString(
-										i18n.language,
-									)}
+								{hydrated && profile?.user?.createdAt
+									? new Date(profile.user.createdAt).toLocaleDateString(
+											i18n.language,
+										)
+									: null}

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cda2e5c-6c89-412c-a343-7a5efeae6ff1

📥 Commits

Reviewing files that changed from the base of the PR and between 53d1ae1 and 5cf6600.

📒 Files selected for processing (1)
  • app/routes/profile.$username.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

<div>
<p className="text-primary text-sm font-bold">
{format(new Date(popupInfo.startTime), 'Pp')}
{dateTimeFormat.format(new Date(popupInfo.startTime))}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous format method displayed a combination of date and time, the new method requests only hours and minutes. Maybe it is fine though as we dont usually have multi-day trips?

Comment thread app/lib/date.ts
if (absDiffInSeconds < ONE_QUARTER_IN_S)
return r.format(-Math.round(diffInSeconds / ONE_MONTH_IN_S), 'month')
if (absDiffInSeconds < ONE_YEAR_IN_S)
return r.format(-Math.round(diffInSeconds / ONE_QUARTER_IN_S), 'quarter')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont know how this is handled in general, but quarter sounds a bit weird to me, what about having only month and year level instead?

const { t } = useTranslation
const { t, i18n } = useTranslation
const isOwner = opts?.isOwner ?? false
const hydrated = useHydrated()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As getColumns is used (conditionally) in the ProfilePage component this line would violate the rules of hooks in react. This was not detected by our linting rules due to the responsible rule being turned off in oxlintrc.json at the moment (my bad 😅). As the hydration state is already present in the ProfilePage component anyway, what about passing it down to getColumns like:

export function getColumns(
  translation: UseTranslationResponse<'data-table', any>,
  opts?: { isOwner?: boolean; hydrated?: boolean },
): ColumnDef<SenseBox>[] {
  const hydrated = opts?.hydrated ?? false
  // ...
}```  

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

date format mismatch on my devices page Replace date-fns dependency with browser-native implementation

2 participants