524 lines
15 KiB
TypeScript
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 extends Record<string, any>, 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 extends Record<string, any>, 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: number;
|
|
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.
|
|
*/
|