NeoScan_Radiologist/app/shared/utils/helpers.ts
2025-08-05 18:01:36 +05:30

524 lines
15 KiB
TypeScript

/*
* File: helpers.ts
* Description: General helper functions for common operations
* Design & Developed by Tech4Biz Solutions
* Copyright (c) Spurrin Innovations. All rights reserved.
*/
import { AlertPriority, PatientStatus } from '../types';
// ============================================================================
// ARRAY HELPERS - Functions for array manipulation and processing
// ============================================================================
/**
* chunk Function
*
* Purpose: Split an array into smaller chunks of specified size
*
* @param array - The array to be chunked
* @param size - The size of each chunk
* @returns Array of arrays, each containing up to 'size' elements
*
* Example:
* chunk([1, 2, 3, 4, 5, 6], 2) → [[1, 2], [3, 4], [5, 6]]
*
* Use case: Pagination, displaying data in groups
*/
export const chunk = <T>(array: T[], size: number): T[][] => {
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
};
/**
* groupBy Function
*
* Purpose: Group array elements by a specified key function
*
* @param array - The array to be grouped
* @param key - Function that returns the grouping key for each element
* @returns Object with keys as group names and values as arrays of grouped items
*
* Example:
* groupBy(patients, patient => patient.department)
* → { 'Emergency': [patient1, patient2], 'ICU': [patient3] }
*
* Use case: Organizing patients by department, status, or priority
*/
export const groupBy = <T, K extends keyof any>(
array: T[],
key: (item: T) => K
): Record<K, T[]> => {
return array.reduce((groups, item) => {
const group = key(item);
if (!groups[group]) {
groups[group] = [];
}
groups[group].push(item);
return groups;
}, {} as Record<K, T[]>);
};
// ============================================================================
// OBJECT HELPERS - Functions for object manipulation and transformation
// ============================================================================
/**
* pick Function
*
* Purpose: Create a new object with only specified properties from the original
*
* @param obj - The source object
* @param keys - Array of property names to include
* @returns New object containing only the specified properties
*
* Example:
* pick({ name: 'John', age: 30, id: 1 }, ['name', 'age'])
* → { name: 'John', age: 30 }
*
* Use case: Extracting specific patient data fields
*/
export const pick = <T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> => {
const result = {} as Pick<T, K>;
keys.forEach(key => {
if (key in obj) {
result[key] = obj[key];
}
});
return result;
};
/**
* omit Function
*
* Purpose: Create a new object excluding specified properties from the original
*
* @param obj - The source object
* @param keys - Array of property names to exclude
* @returns New object without the specified properties
*
* Example:
* omit({ name: 'John', age: 30, id: 1 }, ['id'])
* → { name: 'John', age: 30 }
*
* Use case: Removing sensitive data before sending to API
*/
export const omit = <T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> => {
const result = { ...obj };
keys.forEach(key => {
delete result[key];
});
return result;
};
// ============================================================================
// STRING HELPERS - Functions for string manipulation and formatting
// ============================================================================
/**
* capitalize Function
*
* Purpose: Capitalize the first letter of a string and lowercase the rest
*
* @param str - The string to capitalize
* @returns Capitalized string
*
* Example:
* capitalize('john doe') → 'John doe'
*
* Use case: Formatting patient names, department names
*/
export const capitalize = (str: string): string => {
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};
/**
* truncate Function
*
* Purpose: Truncate a string to specified length and add ellipsis
*
* @param str - The string to truncate
* @param length - Maximum length before truncation
* @returns Truncated string with ellipsis if needed
*
* Example:
* truncate('Very long diagnosis text', 15) → 'Very long diagn...'
*
* Use case: Displaying long text in limited space (diagnoses, notes)
*/
export const truncate = (str: string, length: number): string => {
if (str.length <= length) return str;
return str.slice(0, length) + '...';
};
// ============================================================================
// NUMBER HELPERS - Functions for number manipulation and validation
// ============================================================================
/**
* clamp Function
*
* Purpose: Constrain a number between minimum and maximum values
*
* @param value - The number to clamp
* @param min - Minimum allowed value
* @param max - Maximum allowed value
* @returns Clamped value within the specified range
*
* Example:
* clamp(150, 0, 100) → 100
* clamp(-10, 0, 100) → 0
*
* Use case: Validating vital signs, age ranges, scores
*/
export const clamp = (value: number, min: number, max: number): number => {
return Math.min(Math.max(value, min), max);
};
/**
* roundToDecimal Function
*
* Purpose: Round a number to specified decimal places
*
* @param value - The number to round
* @param decimals - Number of decimal places
* @returns Rounded number
*
* Example:
* roundToDecimal(3.14159, 2) → 3.14
*
* Use case: Formatting vital signs, medication dosages, scores
*/
export const roundToDecimal = (value: number, decimals: number): number => {
return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
};
// ============================================================================
// BOOLEAN HELPERS - Functions for boolean operations and validation
// ============================================================================
/**
* isTruthy Function
*
* Purpose: Check if a value is truthy (converts to true)
*
* @param value - The value to check
* @returns Boolean indicating if value is truthy
*
* Example:
* isTruthy('hello') → true
* isTruthy(0) → false
*
* Use case: Validating form inputs, checking optional fields
*/
export const isTruthy = (value: any): boolean => {
return Boolean(value);
};
/**
* isFalsy Function
*
* Purpose: Check if a value is falsy (converts to false)
*
* @param value - The value to check
* @returns Boolean indicating if value is falsy
*
* Example:
* isFalsy('') → true
* isFalsy(null) → true
*
* Use case: Checking for empty or null values
*/
export const isFalsy = (value: any): boolean => {
return !Boolean(value);
};
// ============================================================================
// FUNCTION HELPERS - Functions for function manipulation and optimization
// ============================================================================
/**
* debounce Function
*
* Purpose: Create a debounced version of a function that delays execution
*
* @param func - The function to debounce
* @param delay - Delay in milliseconds
* @returns Debounced function
*
* Example:
* const debouncedSearch = debounce(searchPatients, 300);
* // Only executes search after 300ms of no input
*
* Use case: Search inputs, API calls, form validation
*/
export const debounce = <T extends (...args: any[]) => any>(
func: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let timeoutId: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func(...args), delay);
};
};
/**
* throttle Function
*
* Purpose: Create a throttled version of a function that limits execution frequency
*
* @param func - The function to throttle
* @param delay - Minimum time between executions in milliseconds
* @returns Throttled function
*
* Example:
* const throttledScroll = throttle(handleScroll, 100);
* // Only executes once every 100ms maximum
*
* Use case: Scroll events, resize events, real-time updates
*/
export const throttle = <T extends (...args: any[]) => any>(
func: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let lastCall = 0;
return (...args: Parameters<T>) => {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func(...args);
}
};
};
// ============================================================================
// MEDICAL HELPERS - Healthcare-specific utility functions
// ============================================================================
/**
* getPriorityColor Function
*
* Purpose: Get the appropriate color for alert priority levels
*
* @param priority - The alert priority level
* @returns Hex color code for the priority
*
* Color Mapping:
* - CRITICAL: Red (#F44336) - Immediate attention required
* - HIGH: Orange (#FF9800) - High priority attention
* - MEDIUM: Blue (#2196F3) - Normal priority
* - LOW: Green (#4CAF50) - Low priority
* - Default: Gray (#9E9E9E) - Unknown priority
*
* Use case: Color-coding alerts, patient cards, status indicators
*/
export const getPriorityColor = (priority: AlertPriority): string => {
switch (priority) {
case 'CRITICAL':
return '#F44336'; // Red for critical alerts
case 'HIGH':
return '#FF9800'; // Orange for high priority
case 'MEDIUM':
return '#2196F3'; // Blue for medium priority
case 'LOW':
return '#4CAF50'; // Green for low priority
default:
return '#9E9E9E'; // Gray for unknown priority
}
};
/**
* getStatusColor Function
*
* Purpose: Get the appropriate color for patient status levels
*
* @param status - The patient status
* @returns Hex color code for the status
*
* Color Mapping:
* - CRITICAL: Red (#F44336) - Critical patient condition
* - ACTIVE: Blue (#2196F3) - Currently under care
* - PENDING: Orange (#FF9800) - Waiting for treatment
* - DISCHARGED: Green (#4CAF50) - Successfully discharged
* - TRANSFERRED: Gray (#9E9E9E) - Transferred to another facility
*
* Use case: Color-coding patient cards, status badges, dashboard indicators
*/
export const getStatusColor = (status: PatientStatus): string => {
switch (status) {
case 'CRITICAL':
return '#F44336'; // Red for critical patients
case 'ACTIVE':
return '#2196F3'; // Blue for active patients
case 'PENDING':
return '#FF9800'; // Orange for pending patients
case 'DISCHARGED':
return '#4CAF50'; // Green for discharged patients
case 'TRANSFERRED':
return '#9E9E9E'; // Gray for transferred patients
default:
return '#9E9E9E'; // Gray for unknown status
}
};
/**
* calculateAge Function
*
* Purpose: Calculate age from date of birth
*
* @param dateOfBirth - The patient's date of birth
* @returns Age in years
*
* Logic:
* - Calculates year difference
* - Adjusts for month and day to get accurate age
* - Handles leap years and month length variations
*
* Example:
* calculateAge(new Date('1990-05-15')) → 33 (if current year is 2023)
*
* Use case: Displaying patient age, age-based calculations, demographics
*/
export const calculateAge = (dateOfBirth: Date): number => {
const today = new Date();
let age = today.getFullYear() - dateOfBirth.getFullYear();
const monthDiff = today.getMonth() - dateOfBirth.getMonth();
// Adjust age if birthday hasn't occurred this year
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < dateOfBirth.getDate())) {
age--;
}
return age;
};
// ============================================================================
// VALIDATION HELPERS - Functions for data validation
// ============================================================================
/**
* isValidEmail Function
*
* Purpose: Validate email address format
*
* @param email - The email address to validate
* @returns Boolean indicating if email is valid
*
* Validation Rules:
* - Must contain @ symbol
* - Must have text before and after @
* - Must have domain extension
*
* Use case: Login forms, user registration, contact information
*/
export const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
/**
* isValidPhone Function
*
* Purpose: Validate phone number format
*
* @param phone - The phone number to validate
* @returns Boolean indicating if phone number is valid
*
* Validation Rules:
* - Minimum 10 digits
* - Allows +, spaces, hyphens, parentheses
* - International format supported
*
* Use case: Contact information, emergency contacts
*/
export const isValidPhone = (phone: string): boolean => {
const phoneRegex = /^\+?[\d\s\-\(\)]{10,}$/;
return phoneRegex.test(phone);
};
/**
* isValidMRN Function
*
* Purpose: Validate Medical Record Number format
*
* @param mrn - The MRN to validate
* @returns Boolean indicating if MRN is valid
*
* Validation Rules:
* - 6-12 characters long
* - Alphanumeric only (A-Z, 0-9)
* - No special characters or spaces
*
* Use case: Patient identification, medical record lookup
*/
export const isValidMRN = (mrn: string): boolean => {
const mrnRegex = /^[A-Z0-9]{6,12}$/;
return mrnRegex.test(mrn);
};
// ============================================================================
// ASYNC HELPERS - Functions for asynchronous operations
// ============================================================================
/**
* sleep Function
*
* Purpose: Create a delay for specified milliseconds
*
* @param ms - Milliseconds to delay
* @returns Promise that resolves after the delay
*
* Example:
* await sleep(1000); // Wait for 1 second
*
* Use case: Rate limiting, loading states, animation delays
*/
export const sleep = (ms: number): Promise<void> => {
return new Promise(resolve => setTimeout(resolve, ms));
};
/**
* retry Function
*
* Purpose: Retry an async function with exponential backoff
*
* @param fn - The async function to retry
* @param retries - Number of retry attempts (default: 3)
* @param delay - Initial delay in milliseconds (default: 1000)
* @returns Promise that resolves with function result or rejects after all retries
*
* Retry Strategy:
* - Exponential backoff (delay doubles after each failure)
* - Stops after specified number of retries
* - Throws error if all retries fail
*
* Example:
* const result = await retry(fetchPatientData, 3, 1000);
*
* Use case: API calls, network requests, database operations
*/
export const retry = async <T>(
fn: () => Promise<T>,
retries: number = 3,
delay: number = 1000
): Promise<T> => {
try {
return await fn();
} catch (error) {
if (retries > 0) {
await sleep(delay);
return retry(fn, retries - 1, delay * 2); // Exponential backoff
}
throw error;
}
};
/*
* End of File: helpers.ts
* Design & Developed by Tech4Biz Solutions
* Copyright (c) Spurrin Innovations. All rights reserved.
*/