Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { useLocale } from './useLocale';
|
||||
|
||||
/**
|
||||
* Composable for number formatting with i18n locale support
|
||||
* Provides methods to format numbers in compact and full display formats
|
||||
*/
|
||||
export function useNumberFormatter() {
|
||||
const { resolvedLocale } = useLocale();
|
||||
|
||||
/**
|
||||
* Formats numbers for display with clean, minimal formatting
|
||||
* - Up to 1,000: show exact number (e.g., 999)
|
||||
* - 1,000 to 999,999: show as "Xk" for exact thousands or "Xk+" for remainder (e.g., 1000 → "1k", 1500 → "1k+")
|
||||
* - 1,000,000+: show in millions with 1 decimal place (e.g., 1,234,000 → "1.2M")
|
||||
*
|
||||
* Uses browser-native Intl.NumberFormat with proper i18n locale support
|
||||
*
|
||||
* @param {number} num - The number to format
|
||||
* @returns {string} Formatted number string
|
||||
*/
|
||||
const formatCompactNumber = num => {
|
||||
if (typeof num !== 'number' || Number.isNaN(num)) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// For numbers between -1000 and 1000 (exclusive), show exact number with locale formatting
|
||||
if (Math.abs(num) < 1000) {
|
||||
return new Intl.NumberFormat(resolvedLocale.value).format(num);
|
||||
}
|
||||
|
||||
// For numbers with absolute value above 1,000,000, show in millions with 1 decimal place
|
||||
if (Math.abs(num) >= 1000000) {
|
||||
const millions = num / 1000000;
|
||||
return new Intl.NumberFormat(resolvedLocale.value, {
|
||||
notation: 'compact',
|
||||
compactDisplay: 'short',
|
||||
maximumFractionDigits: 1,
|
||||
minimumFractionDigits: millions % 1 === 0 ? 0 : 1,
|
||||
}).format(num);
|
||||
}
|
||||
|
||||
// For numbers with absolute value between 1,000 and 1,000,000, show as "Xk" or "Xk+" using floor value
|
||||
// For negative numbers, we want to floor towards zero (truncate), not towards negative infinity
|
||||
const thousands = num >= 0 ? Math.floor(num / 1000) : Math.ceil(num / 1000);
|
||||
const remainder = Math.abs(num) % 1000;
|
||||
const suffix = remainder === 0 ? 'k' : 'k+';
|
||||
return `${new Intl.NumberFormat(resolvedLocale.value).format(thousands)}${suffix}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a number for full display with locale-specific formatting
|
||||
* @param {number} num - The number to format
|
||||
* @returns {string} Formatted number string with full precision and locale formatting (e.g., 1,234,567)
|
||||
*/
|
||||
const formatFullNumber = num => {
|
||||
if (typeof num !== 'number' || Number.isNaN(num)) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return new Intl.NumberFormat(resolvedLocale.value).format(num);
|
||||
};
|
||||
|
||||
return {
|
||||
formatCompactNumber,
|
||||
formatFullNumber,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user