Skip to content

use localized datetime#599

Open
paboldin wants to merge 1 commit intonetbirdio:mainfrom
paboldin:pboldin/features/localized-datetime
Open

use localized datetime#599
paboldin wants to merge 1 commit intonetbirdio:mainfrom
paboldin:pboldin/features/localized-datetime

Conversation

@paboldin
Copy link
Copy Markdown

@paboldin paboldin commented Mar 29, 2026

Summary by CodeRabbit

  • New Features

    • Automatic browser language detection to display dates/times using the user's locale.
  • Improvements

    • Unified and localized date/time formatting across dashboard, admin screens, activity lists, invites, tables, and tooltips for clearer, region-appropriate displays.
    • Minor trailing newline fix.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea32602a-dfda-45fe-933d-d67bf3d8318b

📥 Commits

Reviewing files that changed from the base of the PR and between 6e83c8a and 81f7fd0.

📒 Files selected for processing (10)
  • src/app/(dashboard)/peer/page.tsx
  • src/app/(dashboard)/team/user/page.tsx
  • src/app/invite/page.tsx
  • src/components/DatePickerWithRange.tsx
  • src/layouts/AppLayout.tsx
  • src/modules/activity/ActivityEntryRow.tsx
  • src/modules/common-table-rows/ExpirationDateRow.tsx
  • src/modules/common-table-rows/LastTimeRow.tsx
  • src/modules/reverse-proxy/events/ReverseProxyEventsTimeCell.tsx
  • src/modules/users/UserInvitesTable.tsx
✅ Files skipped from review due to trivial changes (8)
  • src/modules/common-table-rows/LastTimeRow.tsx
  • src/modules/reverse-proxy/events/ReverseProxyEventsTimeCell.tsx
  • src/modules/common-table-rows/ExpirationDateRow.tsx
  • src/modules/users/UserInvitesTable.tsx
  • src/layouts/AppLayout.tsx
  • src/app/invite/page.tsx
  • src/components/DatePickerWithRange.tsx
  • src/modules/activity/ActivityEntryRow.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/(dashboard)/peer/page.tsx
  • src/app/(dashboard)/team/user/page.tsx

📝 Walkthrough

Walkthrough

This PR standardizes date/time formatting across the app to Day.js localized tokens (L, LT) and adds dynamic, client-side Day.js locale detection/loading plus the localizedFormat plugin in the app layout.

Changes

Cohort / File(s) Summary
Date Format Updates
src/app/(dashboard)/peer/page.tsx, src/app/(dashboard)/team/user/page.tsx, src/app/invite/page.tsx, src/components/DatePickerWithRange.tsx, src/modules/activity/ActivityEntryRow.tsx, src/modules/common-table-rows/ExpirationDateRow.tsx, src/modules/common-table-rows/LastTimeRow.tsx, src/modules/reverse-proxy/events/ReverseProxyEventsTimeCell.tsx, src/modules/users/UserInvitesTable.tsx
Replaced explicit Day.js format strings (e.g., D MMMM, YYYY [at] h:mm A, MMM D, YYYY, h:mm:ss A, MMM DD, YYYY) with localized tokens (L, LT, L [at] LT, l, L) for consistent, locale-aware display across UI components.
Locale Configuration
src/layouts/AppLayout.tsx
Added dayjs/plugin/localizedFormat and client-side logic that derives locale candidates from navigator.language/navigator.languages, attempts dynamic imports of matching Day.js locale modules, and sets dayjs.locale(...) (falls back to en).

Sequence Diagram

sequenceDiagram
    participant Browser as Browser (navigator.language)
    participant AppLayout as AppLayout
    participant Dayjs as Day.js
    participant UI as UI Components

    Browser->>AppLayout: provide navigator.language / languages
    AppLayout->>AppLayout: build locale candidates list
    AppLayout->>AppLayout: dynamic import locale module(s)
    AppLayout->>Dayjs: dayjs.extend(localizedFormat)
    AppLayout->>Dayjs: dayjs.locale(importedLocale or "en")
    Dayjs->>UI: localized formats available (L, LT)
    UI->>Browser: render localized date/time
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • mlsmaycon

Poem

🐇 I hopped through code with nimble paws,

Swapping long dates for tiny laws,
The browser hums its tongue so kind,
Day.js paints each time aligned,
Hooray — the timestamps dance and rhyme! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'use localized datetime' directly describes the main change across all modified files, which consistently update date/time formatting to use Day.js localized format tokens.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 29, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DatePickerWithRange.tsx`:
- Around line 90-93: The conditional return in the DatePickerWithRange component
uses dayjs(value.from).format("L").toString() which is redundant because
dayjs().format() already returns a string; remove the unnecessary .toString() so
the early return becomes dayjs(value.from).format("L") and leave the range
return unchanged (the code referencing value.from and value.to should remain the
same).

In `@src/layouts/AppLayout.tsx`:
- Around line 35-45: The current IIFE that reads navigator.language into
localeName should try to import Day.js locales more robustly: normalize
localeName to lowercase, attempt dynamic import for the full locale (e.g.,
'en-us') and if that fails attempt the base language (localeName.split('-')[0],
e.g., 'en'), and if that succeeds call dayjs.locale(<localeCodeString>) with the
string key (not the module object); add catches for import failures and finally
default to dayjs.locale('en') if neither import succeeds; update the IIFE and
its promise handlers around the import('dayjs/locale/' + ...) call to implement
this fallback and error handling using the symbols localeName, dayjs.locale, and
the IIFE wrapper.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee7e381b-84a9-46bc-828c-fb1181eeb055

📥 Commits

Reviewing files that changed from the base of the PR and between 0841cae and 6e83c8a.

📒 Files selected for processing (10)
  • src/app/(dashboard)/peer/page.tsx
  • src/app/(dashboard)/team/user/page.tsx
  • src/app/invite/page.tsx
  • src/components/DatePickerWithRange.tsx
  • src/layouts/AppLayout.tsx
  • src/modules/activity/ActivityEntryRow.tsx
  • src/modules/common-table-rows/ExpirationDateRow.tsx
  • src/modules/common-table-rows/LastTimeRow.tsx
  • src/modules/reverse-proxy/events/ReverseProxyEventsTimeCell.tsx
  • src/modules/users/UserInvitesTable.tsx

Comment on lines +90 to +93
if (!value.to) return dayjs(value.from).format("L").toString();
return `${dayjs(value.from).format("L")} - ${dayjs(
value.to,
).format("MMM DD, YYYY")}`;
).format("L")}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Search for localizedFormat plugin extension in the codebase

# Check if localizedFormat plugin is imported and extended
rg -n "localizedFormat" --type=ts --type=tsx -C3

Repository: netbirdio/dashboard

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Check for localizedFormat plugin usage with correct rg syntax
rg -n "localizedFormat" -C3

Repository: netbirdio/dashboard

Length of output: 983


🏁 Script executed:

#!/bin/bash
# Check the actual code in DatePickerWithRange.tsx
cat -n src/components/DatePickerWithRange.tsx | sed -n '85,95p'

Repository: netbirdio/dashboard

Length of output: 515


Remove redundant .toString() call on line 90.

dayjs().format() already returns a string, so the .toString() call is unnecessary. The localizedFormat plugin is properly extended in AppLayout.tsx, so the "L" format token will work correctly.

🧹 Suggested fix
-    if (!value.to) return dayjs(value.from).format("L").toString();
+    if (!value.to) return dayjs(value.from).format("L");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!value.to) return dayjs(value.from).format("L").toString();
return `${dayjs(value.from).format("L")} - ${dayjs(
value.to,
).format("MMM DD, YYYY")}`;
).format("L")}`;
if (!value.to) return dayjs(value.from).format("L");
return `${dayjs(value.from).format("L")} - ${dayjs(
value.to,
).format("L")}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DatePickerWithRange.tsx` around lines 90 - 93, The conditional
return in the DatePickerWithRange component uses
dayjs(value.from).format("L").toString() which is redundant because
dayjs().format() already returns a string; remove the unnecessary .toString() so
the early return becomes dayjs(value.from).format("L") and leave the range
return unchanged (the code referencing value.from and value.to should remain the
same).

Signed-off-by: Pavel Boldin <boldin.pavel@gmail.com>
@paboldin paboldin force-pushed the pboldin/features/localized-datetime branch from 6e83c8a to 81f7fd0 Compare March 29, 2026 17:07
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.

2 participants