2025-12-03 21:56:50 +00:00
|
|
|
/**
|
|
|
|
|
* Utilitaires pour le formatage des données
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export function formatFileSize(bytes: number): string {
|
|
|
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
|
|
|
|
|
|
const k = 1024;
|
|
|
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatNumber(num: number): string {
|
|
|
|
|
if (num < 1000) {
|
|
|
|
|
return num.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (num < 1000000) {
|
2025-12-13 02:34:34 +00:00
|
|
|
return `${(num / 1000).toFixed(1)}K`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (num < 1000000000) {
|
2025-12-13 02:34:34 +00:00
|
|
|
return `${(num / 1000000).toFixed(1)}M`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
return `${(num / 1000000000).toFixed(1)}B`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
export function formatCurrency(
|
|
|
|
|
amount: number,
|
|
|
|
|
currency: string = 'EUR',
|
|
|
|
|
): string {
|
2025-12-03 21:56:50 +00:00
|
|
|
return new Intl.NumberFormat('fr-FR', {
|
|
|
|
|
style: 'currency',
|
|
|
|
|
currency,
|
|
|
|
|
}).format(amount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatPercentage(value: number, decimals: number = 1): string {
|
|
|
|
|
return `${(value * 100).toFixed(decimals)}%`;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
export function truncate(
|
|
|
|
|
text: string,
|
|
|
|
|
maxLength: number,
|
|
|
|
|
suffix: string = '...',
|
|
|
|
|
): string {
|
2025-12-03 21:56:50 +00:00
|
|
|
if (text.length <= maxLength) {
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return text.substring(0, maxLength - suffix.length) + suffix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function capitalize(text: string): string {
|
|
|
|
|
return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function capitalizeWords(text: string): string {
|
|
|
|
|
return text.split(' ').map(capitalize).join(' ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function slugify(text: string): string {
|
|
|
|
|
return text
|
|
|
|
|
.toLowerCase()
|
|
|
|
|
.trim()
|
|
|
|
|
.replace(/[^\w\s-]/g, '')
|
|
|
|
|
.replace(/[\s_-]+/g, '-')
|
|
|
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function initials(name: string): string {
|
|
|
|
|
return name
|
|
|
|
|
.split(' ')
|
2025-12-13 02:34:34 +00:00
|
|
|
.map((word) => word.charAt(0).toUpperCase())
|
2025-12-03 21:56:50 +00:00
|
|
|
.join('')
|
|
|
|
|
.substring(0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatUsername(username: string): string {
|
|
|
|
|
return `@${username}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatEmail(email: string): string {
|
|
|
|
|
const [localPart, domain] = email.split('@');
|
|
|
|
|
if (localPart.length > 3) {
|
|
|
|
|
return `${localPart.substring(0, 3)}***@${domain}`;
|
|
|
|
|
}
|
|
|
|
|
return email;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatPhoneNumber(phone: string): string {
|
|
|
|
|
// Format français: 06 12 34 56 78
|
|
|
|
|
const cleaned = phone.replace(/\D/g, '');
|
|
|
|
|
if (cleaned.length === 10) {
|
2025-12-13 02:34:34 +00:00
|
|
|
return cleaned.replace(
|
|
|
|
|
/(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/,
|
|
|
|
|
'$1 $2 $3 $4 $5',
|
|
|
|
|
);
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
return phone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatBytes(bytes: number, decimals: number = 2): string {
|
|
|
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
|
|
|
|
|
|
const k = 1024;
|
|
|
|
|
const dm = decimals < 0 ? 0 : decimals;
|
|
|
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
|
|
|
|
|
|
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatDuration(seconds: number): string {
|
|
|
|
|
const hours = Math.floor(seconds / 3600);
|
|
|
|
|
const minutes = Math.floor((seconds % 3600) / 60);
|
|
|
|
|
const remainingSeconds = Math.floor(seconds % 60);
|
|
|
|
|
|
|
|
|
|
if (hours > 0) {
|
|
|
|
|
return `${hours}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formatTimeAgo(date: Date | string): string {
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const past = new Date(date);
|
|
|
|
|
const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000);
|
|
|
|
|
|
|
|
|
|
if (diffInSeconds < 60) {
|
2025-12-13 02:34:34 +00:00
|
|
|
return "À l'instant";
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
|
|
|
if (diffInMinutes < 60) {
|
|
|
|
|
return `Il y a ${diffInMinutes} min`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
|
|
|
if (diffInHours < 24) {
|
|
|
|
|
return `Il y a ${diffInHours}h`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInDays = Math.floor(diffInHours / 24);
|
|
|
|
|
if (diffInDays < 7) {
|
|
|
|
|
return `Il y a ${diffInDays}j`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInWeeks = Math.floor(diffInDays / 7);
|
|
|
|
|
if (diffInWeeks < 4) {
|
|
|
|
|
return `Il y a ${diffInWeeks} sem`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInMonths = Math.floor(diffInDays / 30);
|
|
|
|
|
if (diffInMonths < 12) {
|
|
|
|
|
return `Il y a ${diffInMonths} mois`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const diffInYears = Math.floor(diffInDays / 365);
|
|
|
|
|
return `Il y a ${diffInYears} an${diffInYears > 1 ? 's' : ''}`;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
export function formatList(
|
|
|
|
|
items: string[],
|
|
|
|
|
conjunction: string = 'et',
|
|
|
|
|
): string {
|
2025-12-03 21:56:50 +00:00
|
|
|
if (items.length === 0) return '';
|
|
|
|
|
if (items.length === 1) return items[0];
|
|
|
|
|
if (items.length === 2) return `${items[0]} ${conjunction} ${items[1]}`;
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
const lastItem = items[items.length - 1];
|
|
|
|
|
const otherItems = items.slice(0, -1);
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
return `${otherItems.join(', ')} ${conjunction} ${lastItem}`;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-13 02:34:34 +00:00
|
|
|
export function formatPlural(
|
|
|
|
|
count: number,
|
|
|
|
|
singular: string,
|
|
|
|
|
plural?: string,
|
|
|
|
|
): string {
|
2025-12-03 21:56:50 +00:00
|
|
|
if (count === 0 || count === 1) {
|
|
|
|
|
return `${count} ${singular}`;
|
|
|
|
|
}
|
2025-12-13 02:34:34 +00:00
|
|
|
|
|
|
|
|
return `${count} ${plural || `${singular}s`}`;
|
2025-12-03 21:56:50 +00:00
|
|
|
}
|