Files
Inventory/app/utils/formatters/phone.ts
2025-09-25 14:44:42 +02:00

68 lines
2.0 KiB
TypeScript

/**
* Utilities to normalize and format phone numbers without relying on external libraries.
* The helpers keep the behaviour permissive to avoid breaking existing flows while
* still providing a single place where formatting rules live.
*/
/** Matches characters that should be kept when normalising a phone number. */
const PHONE_CHAR_PATTERN = /[^+\d]/g
/**
* Normalises a phone number by trimming whitespace, removing spacing/separators and
* converting international prefixes written with `00` to their `+` variant.
*/
export const normalizePhone = (rawValue: string): string => {
const trimmed = (rawValue || '').trim()
if (!trimmed) {
return ''
}
const cleaned = trimmed.replace(PHONE_CHAR_PATTERN, '')
if (cleaned.startsWith('00')) {
return `+${cleaned.slice(2)}`
}
return cleaned
}
/**
* Formats a phone number by grouping digits by two while keeping any international
* prefix. The function remains tolerant to partially entered numbers.
*/
export const formatPhone = (rawValue: string): string => {
const normalized = normalizePhone(rawValue)
if (!normalized) {
return ''
}
const hasInternationalPrefix = normalized.startsWith('+')
const prefix = hasInternationalPrefix ? normalized.slice(0, 1) : ''
const digits = hasInternationalPrefix ? normalized.slice(1) : normalized
const groups = digits.match(/.{1,2}/g) ?? []
const grouped = groups.join(' ')
return prefix ? `${prefix}${grouped ? ' ' : ''}${grouped}` : grouped
}
/**
* Masks a phone number for display purposes by replacing the middle digits with ·.
* Useful for UI fragments where the full number should not be exposed.
*/
export const maskPhone = (rawValue: string): string => {
const normalized = normalizePhone(rawValue)
if (!normalized) {
return ''
}
if (normalized.length <= 4) {
return normalized
}
const start = normalized.slice(0, 2)
const end = normalized.slice(-2)
const maskedMiddle = '·'.repeat(Math.max(0, normalized.length - 4))
return `${start}${maskedMiddle}${end}`
}