Phone Number Helpers
Phone number validation, formatting, and processing utilities for international phone numbers in the WorkPayCore frontend application.
Overviewβ
The phone number helpers provide utilities for validating, formatting, and processing phone numbers across different countries and regions, with support for international formats.
Core Functionsβ
validatePhoneNumber(phoneNumber, countryCode?)β
Validates a phone number format and returns validation status.
Parameters:
phoneNumber(string): Phone number to validatecountryCode(string, optional): ISO country code (e.g., 'US', 'KE', 'NG')
Returns:
object: Validation result with status and details
Example:
import { validatePhoneNumber } from '@/utils/helpers/phone-number';
// Validate US phone number
const usResult = validatePhoneNumber('+1-555-123-4567', 'US');
console.log(usResult);
// Returns: { isValid: true, country: 'US', format: 'international' }
// Validate Kenyan phone number
const keResult = validatePhoneNumber('+254712345678', 'KE');
console.log(keResult);
// Returns: { isValid: true, country: 'KE', format: 'international' }
// Invalid phone number
const invalidResult = validatePhoneNumber('123', 'US');
console.log(invalidResult);
// Returns: { isValid: false, error: 'Invalid phone number format' }
Use Cases:
- Form validation
- User registration
- Contact information verification
- International number validation
formatPhoneNumber(phoneNumber, format?, countryCode?)β
Formats a phone number according to specified format and country standards.
Parameters:
phoneNumber(string): Raw phone number to formatformat(string, optional): Format type ('international', 'national', 'e164')countryCode(string, optional): ISO country code
Returns:
string: Formatted phone number or original if formatting fails
Example:
import { formatPhoneNumber } from '@/utils/helpers/phone-number';
// Format to international standard
const international = formatPhoneNumber('5551234567', 'international', 'US');
console.log(international);
// Returns: '+1 555 123 4567'
// Format to national standard
const national = formatPhoneNumber('5551234567', 'national', 'US');
console.log(national);
// Returns: '(555) 123-4567'
// Format to E.164 standard
const e164 = formatPhoneNumber('555 123 4567', 'e164', 'US');
console.log(e164);
// Returns: '+15551234567'
// Kenyan number formatting
const kenyan = formatPhoneNumber('712345678', 'international', 'KE');
console.log(kenyan);
// Returns: '+254 712 345 678'
Use Cases:
- Display formatting
- API data preparation
- Consistent number storage
- User interface standardization
parsePhoneNumber(phoneNumber)β
Parses a phone number and extracts components like country code, area code, and number.
Parameters:
phoneNumber(string): Phone number to parse
Returns:
object: Parsed phone number components
Example:
import { parsePhoneNumber } from '@/utils/helpers/phone-number';
// Parse US number
const usNumber = parsePhoneNumber('+1-555-123-4567');
console.log(usNumber);
// Returns: {
// countryCode: '1',
// areaCode: '555',
// number: '1234567',
// extension: null,
// isValid: true
// }
// Parse international number
const intlNumber = parsePhoneNumber('+44 20 7946 0958');
console.log(intlNumber);
// Returns: {
// countryCode: '44',
// areaCode: '20',
// number: '79460958',
// extension: null,
// isValid: true
// }
Use Cases:
- Number analysis
- Database storage optimization
- Search functionality
- Number component extraction
getCountryFromPhoneNumber(phoneNumber)β
Determines the country of origin for a phone number based on country code.
Parameters:
phoneNumber(string): Phone number to analyze
Returns:
object: Country information or null if not found
Example:
import { getCountryFromPhoneNumber } from '@/utils/helpers/phone-number';
// US number
const usCountry = getCountryFromPhoneNumber('+1-555-123-4567');
console.log(usCountry);
// Returns: { code: 'US', name: 'United States', dialCode: '+1' }
// Kenyan number
const keCountry = getCountryFromPhoneNumber('+254712345678');
console.log(keCountry);
// Returns: { code: 'KE', name: 'Kenya', dialCode: '+254' }
// Unknown number
const unknown = getCountryFromPhoneNumber('123456');
console.log(unknown);
// Returns: null
Use Cases:
- Automatic country detection
- Billing region determination
- Localization services
- Fraud detection
Regional Support Functionsβ
getSupportedCountries()β
Returns list of supported countries for phone number operations.
Parameters:
- None
Returns:
array: Array of supported country objects
Example:
import { getSupportedCountries } from '@/utils/helpers/phone-number';
const countries = getSupportedCountries();
console.log(countries);
// Returns: [
// { code: 'US', name: 'United States', dialCode: '+1', flag: 'πΊπΈ' },
// { code: 'KE', name: 'Kenya', dialCode: '+254', flag: 'π°πͺ' },
// { code: 'NG', name: 'Nigeria', dialCode: '+234', flag: 'π³π¬' },
// // ... more countries
// ]
Use Cases:
- Country selector components
- Validation rule configuration
- International calling features
- Regional service availability
getDialCodeForCountry(countryCode)β
Gets the international dial code for a specific country.
Parameters:
countryCode(string): ISO country code
Returns:
string: Dial code or null if not found
Example:
import { getDialCodeForCountry } from '@/utils/helpers/phone-number';
getDialCodeForCountry('US'); // Returns: '+1'
getDialCodeForCountry('KE'); // Returns: '+254'
getDialCodeForCountry('GB'); // Returns: '+44'
getDialCodeForCountry('XX'); // Returns: null
Use Cases:
- Phone input prefilling
- Country selection handling
- International calling setup
- Number formatting preparation
Advanced Usage Examplesβ
Phone Input Componentβ
import {
validatePhoneNumber,
formatPhoneNumber,
getSupportedCountries,
} from '@/utils/helpers/phone-number';
const PhoneInput = ({ value, onChange, onValidation }) => {
const [selectedCountry, setSelectedCountry] = useState('US');
const [phoneNumber, setPhoneNumber] = useState(value || '');
const [isValid, setIsValid] = useState(false);
const countries = getSupportedCountries();
const handlePhoneChange = newNumber => {
setPhoneNumber(newNumber);
// Validate phone number
const validation = validatePhoneNumber(newNumber, selectedCountry);
setIsValid(validation.isValid);
// Format for display
const formatted = formatPhoneNumber(newNumber, 'national', selectedCountry);
// Notify parent component
onChange?.(formatted);
onValidation?.(validation);
};
const handleCountryChange = countryCode => {
setSelectedCountry(countryCode);
// Revalidate with new country
if (phoneNumber) {
handlePhoneChange(phoneNumber);
}
};
return (
<div className='phone-input'>
<select
value={selectedCountry}
onChange={e => handleCountryChange(e.target.value)}
className='country-selector'
>
{countries.map(country => (
<option key={country.code} value={country.code}>
{country.flag} {country.name} ({country.dialCode})
</option>
))}
</select>
<input
type='tel'
value={phoneNumber}
onChange={e => handlePhoneChange(e.target.value)}
placeholder='Phone number'
className={`phone-field ${isValid ? 'valid' : 'invalid'}`}
/>
{!isValid && phoneNumber && (
<span className='error'>Invalid phone number format</span>
)}
</div>
);
};
Phone Number Validation Hookβ
import {
validatePhoneNumber,
formatPhoneNumber,
} from '@/utils/helpers/phone-number';
const usePhoneValidation = (initialCountry = 'US') => {
const [country, setCountry] = useState(initialCountry);
const [phoneNumber, setPhoneNumber] = useState('');
const [validation, setValidation] = useState({ isValid: false });
const validatePhone = useCallback(
(number, countryCode = country) => {
const result = validatePhoneNumber(number, countryCode);
setValidation(result);
return result;
},
[country],
);
const formatPhone = useCallback(
(number, format = 'national') => {
return formatPhoneNumber(number, format, country);
},
[country],
);
const updatePhone = number => {
setPhoneNumber(number);
validatePhone(number);
};
const updateCountry = newCountry => {
setCountry(newCountry);
if (phoneNumber) {
validatePhone(phoneNumber, newCountry);
}
};
return {
phoneNumber,
country,
validation,
updatePhone,
updateCountry,
formatPhone,
validatePhone,
};
};
// Usage in form
const ContactForm = () => {
const {
phoneNumber,
country,
validation,
updatePhone,
updateCountry,
formatPhone,
} = usePhoneValidation();
const handleSubmit = e => {
e.preventDefault();
if (!validation.isValid) {
alert('Please enter a valid phone number');
return;
}
const formattedPhone = formatPhone(phoneNumber, 'e164');
// Submit with formatted phone number
submitForm({ phone: formattedPhone, country });
};
return (
<form onSubmit={handleSubmit}>
<PhoneInput
value={phoneNumber}
country={country}
onChange={updatePhone}
onCountryChange={updateCountry}
/>
<button type='submit' disabled={!validation.isValid}>
Submit
</button>
</form>
);
};
Bulk Phone Processingβ
import {
validatePhoneNumber,
formatPhoneNumber,
parsePhoneNumber,
} from '@/utils/helpers/phone-number';
const processBulkPhoneNumbers = (phoneList, defaultCountry = 'US') => {
return phoneList.map(item => {
const { phone, country = defaultCountry, ...rest } = item;
// Parse and validate
const parsed = parsePhoneNumber(phone);
const validation = validatePhoneNumber(phone, country);
// Format for different uses
const formatted = {
display: formatPhoneNumber(phone, 'national', country),
storage: formatPhoneNumber(phone, 'e164', country),
international: formatPhoneNumber(phone, 'international', country),
};
return {
...rest,
originalPhone: phone,
country,
parsed,
validation,
formatted,
isProcessed: true,
};
});
};
// Usage for employee data processing
const processEmployeePhones = async employees => {
const processed = processBulkPhoneNumbers(employees);
// Filter valid phone numbers
const validPhones = processed.filter(emp => emp.validation.isValid);
// Group by country
const byCountry = validPhones.reduce((acc, emp) => {
const country = emp.country;
if (!acc[country]) acc[country] = [];
acc[country].push(emp);
return acc;
}, {});
return {
total: processed.length,
valid: validPhones.length,
invalid: processed.length - validPhones.length,
byCountry,
processed,
};
};
International Calling Featuresβ
import {
getCountryFromPhoneNumber,
getDialCodeForCountry,
formatPhoneNumber,
} from '@/utils/helpers/phone-number';
const useInternationalCalling = () => {
const [currentCountry, setCurrentCountry] = useState('US');
const calculateCallCost = (phoneNumber, duration) => {
const targetCountry = getCountryFromPhoneNumber(phoneNumber);
if (!targetCountry) {
return { error: 'Unknown destination country' };
}
// Mock rate calculation
const rates = {
US: 0.02,
KE: 0.15,
NG: 0.18,
GB: 0.05,
};
const rate = rates[targetCountry.code] || 0.25;
const cost = (duration / 60) * rate;
return {
targetCountry,
rate,
duration,
cost: cost.toFixed(2),
formattedNumber: formatPhoneNumber(phoneNumber, 'international'),
};
};
const prepareInternationalCall = phoneNumber => {
const country = getCountryFromPhoneNumber(phoneNumber);
const dialCode = getDialCodeForCountry(currentCountry);
if (country && country.code !== currentCountry) {
return {
isInternational: true,
targetCountry: country,
dialCode,
formattedNumber: formatPhoneNumber(phoneNumber, 'international'),
estimatedRate: calculateCallCost(phoneNumber, 60).rate,
};
}
return {
isInternational: false,
targetCountry: null,
dialCode,
formattedNumber: formatPhoneNumber(
phoneNumber,
'national',
currentCountry,
),
};
};
return {
currentCountry,
setCurrentCountry,
calculateCallCost,
prepareInternationalCall,
};
};
Best Practicesβ
- Always Validate: Validate phone numbers before processing or storage
- Consistent Formatting: Use E.164 format for storage, national for display
- Country Context: Always provide country context when possible
- Error Handling: Handle invalid numbers gracefully
- Performance: Cache country lists and validation rules
Common Patternsβ
Phone Number Storageβ
// Store in E.164 format
const phoneForStorage = formatPhoneNumber(userInput, 'e164', country);
// Display in national format
const phoneForDisplay = formatPhoneNumber(storedPhone, 'national', country);
Form Validationβ
const isPhoneValid = (phone, country) => {
const validation = validatePhoneNumber(phone, country);
return validation.isValid;
};
Related Utilitiesβ
- String Utilities - For text processing
- General Helpers - For validation utilities
- Country Helpers - For country-related operations
TypeScript Definitionsβ
interface PhoneValidation {
isValid: boolean;
country?: string;
format?: string;
error?: string;
}
interface ParsedPhoneNumber {
countryCode: string;
areaCode: string;
number: string;
extension: string | null;
isValid: boolean;
}
interface CountryInfo {
code: string;
name: string;
dialCode: string;
flag?: string;
}
export function validatePhoneNumber(
phoneNumber: string,
countryCode?: string,
): PhoneValidation;
export function formatPhoneNumber(
phoneNumber: string,
format?: string,
countryCode?: string,
): string;
export function parsePhoneNumber(phoneNumber: string): ParsedPhoneNumber;
export function getCountryFromPhoneNumber(
phoneNumber: string,
): CountryInfo | null;
export function getSupportedCountries(): CountryInfo[];
export function getDialCodeForCountry(countryCode: string): string | null;
Dependenciesβ
- libphonenumber-js: For phone number parsing and validation
- Country data: For country codes and dial codes
- Regex patterns: For format validation