55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
/**
|
|
* Generic formatting utilities
|
|
* These are reusable formatting functions used across the app
|
|
*/
|
|
|
|
/**
|
|
* Format duration in minutes to a human-readable string
|
|
* @param minutes - Duration in minutes (number or string)
|
|
* @returns Formatted string like "30m", "1h", "1h 30m"
|
|
*
|
|
* @example
|
|
* formatDuration(30) // "30m"
|
|
* formatDuration(60) // "1h"
|
|
* formatDuration(90) // "1h 30m"
|
|
*/
|
|
export const formatDuration = (minutes: number | string | undefined): string => {
|
|
const mins = typeof minutes === "string" ? parseInt(minutes) || 0 : minutes || 0;
|
|
if (mins <= 0) return "0m";
|
|
if (mins < 60) return `${mins}m`;
|
|
const hours = Math.floor(mins / 60);
|
|
const remainingMins = mins % 60;
|
|
return remainingMins > 0 ? `${hours}h ${remainingMins}m` : `${hours}h`;
|
|
};
|
|
|
|
/**
|
|
* Truncate text to a maximum length with ellipsis
|
|
* @param text - The text to truncate
|
|
* @param maxLength - Maximum length (default: 20)
|
|
* @returns Truncated text with "..." if it exceeds maxLength
|
|
*
|
|
* @example
|
|
* truncateTitle("Very long title here", 10) // "Very long..."
|
|
*/
|
|
export const truncateTitle = (text: string, maxLength: number = 20): string => {
|
|
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
|
};
|
|
|
|
/**
|
|
* Format an app ID to a display name
|
|
* Converts kebab-case to Title Case
|
|
*
|
|
* @param appId - The app identifier (e.g., "google-meet", "cal-video")
|
|
* @returns Formatted display name (e.g., "Google Meet", "Cal Video")
|
|
*
|
|
* @example
|
|
* formatAppIdToDisplayName("google-meet") // "Google Meet"
|
|
* formatAppIdToDisplayName("cal-video") // "Cal Video"
|
|
*/
|
|
export const formatAppIdToDisplayName = (appId: string): string => {
|
|
return appId
|
|
.split("-")
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
.join(" ");
|
|
};
|