flowstate/utils/user.ts
Chneemann 3db1a18086
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 43s
refactor(member): update member status stat to dynamically display capitalized user role
2026-08-21 04:09:03 +02:00

93 lines
3.1 KiB
TypeScript

/**
* @file utils/user.ts
* @description Utility functions for user formatting, initials generation, and name capitalization.
*/
/**
* Capitalizes the first letter of a given string.
*
* @param {string} [str] - The string to capitalize.
* @returns {string} The capitalized string or an empty string if undefined/empty.
*/
export function capitalize(str?: string): string {
if (!str) return "";
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}
/**
* Generates the full name with properly capitalized first and last names.
*
* @param {string} [firstName] - The user's first name.
* @param {string} [lastName] - The user's last name.
* @returns {string} The formatted full name.
*/
export function getFullName(firstName?: string, lastName?: string): string {
const formattedFirst = capitalize(firstName);
const formattedLast = capitalize(lastName);
return `${formattedFirst} ${formattedLast}`.trim();
}
/**
* Generates uppercase initials from a user's first and last name.
*
* @param {string} [firstName] - The user's first name.
* @param {string} [lastName] - The user's last name.
* @returns {string} The computed initials (e.g., "JD") or a fallback question mark "?" if neither is provided.
*/
export function getInitials(firstName?: string, lastName?: string): string {
const first = firstName?.[0] || "";
const last = lastName?.[0] || "";
return `${first}${last}`.toUpperCase() || "?";
}
/**
* Returns the CSS classes for the user's online status indicator.
*
* @param {boolean} isOnline - Whether the user is currently online.
* @returns {string} Tailwind CSS classes representing the status dot indicator.
*/
export function getStatusColor(isOnline: boolean): string {
return isOnline
? "bg-emerald-500 shadow-emerald-500/50"
: "bg-slate-600 shadow-none";
}
/**
* Formats a given login date into a human-readable relative time string (e.g., "2 days ago").
*
* @param {Date | string | null} [dateInput] - The login date to format.
* @returns {string} A relative time string formatted via Intl.RelativeTimeFormat, or a fallback message if no date is provided.
*/
export function formatTimeAgo(dateInput?: Date | string | null): string {
if (!dateInput) return "Never logged in";
const date = new Date(dateInput);
const now = new Date();
const diffInSeconds = Math.round((date.getTime() - now.getTime()) / 1000);
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
const intervals: { limit: number; unit: Intl.RelativeTimeFormatUnit }[] = [
{ limit: 60, unit: "second" },
{ limit: 3600, unit: "minute" },
{ limit: 86400, unit: "hour" },
{ limit: 2592000, unit: "day" },
{ limit: 31536000, unit: "month" },
{ limit: Infinity, unit: "year" },
];
const divisors = [1, 60, 3600, 86400, 2592000, 31536000];
for (let i = 0; i < intervals.length; i++) {
const divisor = divisors[i];
if (
Math.abs(diffInSeconds) < intervals[i].limit ||
i === intervals.length - 1
) {
const value = Math.round(diffInSeconds / divisor);
return rtf.format(value, intervals[i].unit);
}
}
return "Never logged in";
}