-
Notifications
You must be signed in to change notification settings - Fork 989
refactor: Replace date-fns with native Intl APIs and update phone uti… #668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,18 +3,33 @@ | |||||
| * @module lib/utils/formatting | ||||||
| */ | ||||||
|
|
||||||
| import { format, formatDistanceToNow } from 'date-fns'; | ||||||
| const dateFormatter = new Intl.DateTimeFormat('en-US', { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). |
||||||
| month: 'short', | ||||||
| day: 'numeric', | ||||||
| year: 'numeric' | ||||||
| }); | ||||||
|
|
||||||
| const relativeFormatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
|
||||||
| const relativeFormatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); | |
| const relativeFormatter = new Intl.RelativeTimeFormat('en-US', { numeric: 'auto' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'export' is only available in ES6 (use 'esversion: 6').
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'export' is only available in ES6 (use 'esversion: 6').
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,27 @@ | ||
| import { isValidPhoneNumber, parsePhoneNumber, isPossiblePhoneNumber } from 'libphonenumber-js'; | ||
| /** @type {Promise<typeof import('libphonenumber-js')> | null} */ | ||
| let _lib = null; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). |
||
|
|
||
| function getLib() { | ||
| if (!_lib) _lib = import('libphonenumber-js'); | ||
| return _lib; | ||
| } | ||
|
|
||
| /** | ||
| * Validates a phone number and returns validation result | ||
| * @param {string} phoneNumber - The phone number to validate | ||
| * @param {string} [defaultCountry] - Default country code (e.g., 'US', 'IN') | ||
| * @returns {{ isValid: boolean, formatted?: string, error?: string }} | ||
| * @returns {Promise<{ isValid: boolean, formatted?: string, error?: string }>} | ||
| */ | ||
| export function validatePhoneNumber(phoneNumber, defaultCountry) { | ||
| export async function validatePhoneNumber(phoneNumber, defaultCountry) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'export' is only available in ES6 (use 'esversion: 6'). |
||
| if (!phoneNumber || phoneNumber.trim() === '') { | ||
| return { isValid: true }; // Allow empty phone numbers | ||
| } | ||
|
|
||
| const trimmed = phoneNumber.trim(); | ||
|
|
||
| try { | ||
| const { isValidPhoneNumber, parsePhoneNumber, isPossiblePhoneNumber } = await getLib(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). |
||
|
|
||
| // If the number starts with +, validate as international | ||
| if (trimmed.startsWith('+')) { | ||
| const isValid = isValidPhoneNumber(trimmed); | ||
|
|
@@ -88,12 +96,13 @@ export function validatePhoneNumber(phoneNumber, defaultCountry) { | |
| * Formats a phone number for display | ||
| * @param {string} phoneNumber - The phone number to format | ||
| * @param {string} defaultCountry - Default country code | ||
| * @returns {string} Formatted phone number or original if invalid | ||
| * @returns {Promise<string>} Formatted phone number or original if invalid | ||
| */ | ||
| export function formatPhoneNumber(phoneNumber, defaultCountry = 'US') { | ||
| export async function formatPhoneNumber(phoneNumber, defaultCountry = 'US') { | ||
| if (!phoneNumber) return ''; | ||
|
|
||
| try { | ||
| const { parsePhoneNumber } = await getLib(); | ||
| // @ts-ignore - defaultCountry is a valid CountryCode | ||
| const parsed = parsePhoneNumber(phoneNumber, { defaultCountry }); | ||
| return parsed.formatInternational(); | ||
|
|
@@ -106,14 +115,16 @@ export function formatPhoneNumber(phoneNumber, defaultCountry = 'US') { | |
| * Formats a phone number for storage (E.164 format) | ||
| * @param {string} phoneNumber - The phone number to format | ||
| * @param {string} [defaultCountry] - Default country code | ||
| * @returns {string} E.164 formatted phone number or original if invalid | ||
| * @returns {Promise<string>} E.164 formatted phone number or original if invalid | ||
| */ | ||
| export function formatPhoneForStorage(phoneNumber, defaultCountry) { | ||
| export async function formatPhoneForStorage(phoneNumber, defaultCountry) { | ||
| if (!phoneNumber) return ''; | ||
|
|
||
| const trimmed = phoneNumber.trim(); | ||
|
|
||
| try { | ||
| const { parsePhoneNumber } = await getLib(); | ||
|
|
||
| // If starts with +, parse as international | ||
| if (trimmed.startsWith('+')) { | ||
| const parsed = parsePhoneNumber(trimmed); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -78,11 +78,11 @@ export const actions = { | |
| // Validate phone if provided | ||
| let formattedPhone = null; | ||
| if (phone && phone.trim().length > 0) { | ||
| const phoneValidation = validatePhoneNumber(phone.trim()); | ||
| const phoneValidation = await validatePhoneNumber(phone.trim()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). |
||
| if (!phoneValidation.isValid) { | ||
| errors.phone = phoneValidation.error || 'Please enter a valid phone number'; | ||
| } else { | ||
| formattedPhone = formatPhoneForStorage(phone.trim()); | ||
| formattedPhone = await formatPhoneForStorage(phone.trim()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing semicolon. |
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| let isEditing = $state(false); | ||
| let isSubmitting = $state(false); | ||
| let phoneError = $state(''); | ||
| let formattedDisplayPhone = $state(''); | ||
|
|
||
| // Form data state - initialized by $effect below | ||
| let formData = $state({ | ||
|
|
@@ -36,14 +37,23 @@ | |
| } | ||
| }); | ||
|
|
||
| // Format phone for display (async, resolved into state) | ||
| $effect(() => { | ||
| if (data.user.phone) { | ||
| formatPhoneNumber(data.user.phone).then((f) => (formattedDisplayPhone = f)); | ||
| } else { | ||
| formattedDisplayPhone = ''; | ||
| } | ||
| }); | ||
|
Comment on lines
+40
to
+47
|
||
|
|
||
| // Validate phone number on input | ||
| function validatePhone() { | ||
| async function validatePhone() { | ||
| if (!formData.phone.trim()) { | ||
| phoneError = ''; | ||
| return; | ||
| } | ||
|
|
||
| const validation = validatePhoneNumber(formData.phone); | ||
| const validation = await validatePhoneNumber(formData.phone); | ||
| if (!validation.isValid) { | ||
| phoneError = validation.error || 'Invalid phone number'; | ||
| } else { | ||
|
|
@@ -277,7 +287,7 @@ | |
| Phone Number | ||
| </div> | ||
| <p class="text-foreground"> | ||
| {data.user.phone ? formatPhoneNumber(data.user.phone) : 'Not provided'} | ||
| {formattedDisplayPhone || data.user.phone || 'Not provided'} | ||
| </p> | ||
| </div> | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).