// Common Utility file import { dateFormat, startOfToday, dateFormat_hrental } from './dates'; export const isValidDate = (date: Date) => { return date && !isNaN(date.getTime()); }; export const _getDate = (date: string | number | Date) => { const type = typeof date; let departDate; if (type === 'number') { departDate = new Date(date); } else if (typeof date === 'string') { departDate = date.split('/'); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access departDate = new Date(`${departDate[1]}/${departDate[0]}/${departDate[2]}`); } else if (date instanceof Date) { departDate = date; } return departDate; }; export const isOldDate = (dateValue: number) => { const currDate = new Date(); currDate.setHours(0, 0, 0, 0); return dateValue < currDate.getTime(); }; /** Returns whether the value is a function. Acts as a type guard. */ export const isFunction = (value: unknown) => { return typeof value === 'function'; }; /** * Safely invoke the function with the given arguments, * if it is indeed a function, and return its value. */ export const safeInvoke = (func: unknown = undefined, ...args: unknown[]) => { return isFunction(func) && func(...args); }; export { startOfToday, dateFormat_hrental, dateFormat }; export const isEmpty = (obj: unknown) => { if (obj instanceof Date) { return false; } // null and undefined are "empty" if (obj == null || obj == 'undefined') { return true; } const isNumber = (value: unknown) => Object.prototype.toString.call(value) === '[object Number]'; const isNaN = (value: unknown) => isNumber(value) && typeof value === 'number' && isNaN(value); if (isNumber(obj)) { return isNaN(obj); } /** Assume if it has a length property with a non-zero value * that that property is correct. */ if (typeof obj === 'object' && 'length' in obj && typeof obj.length === 'number' && obj.length > 0) { return false; } if (typeof obj === 'object' && 'length' in obj && typeof obj.length === 'number' && obj.length === 0) { return true; } /** If it isn't an object at this point * it is empty, but it can't be anything *but* empty * Is it empty? Depends on your application. */ if (typeof obj !== 'object') { return true; } /** Otherwise, does it have any properties of its own? * Note that this doesn't handle * toString and valueOf enumeration bugs in IE < 9 */ const keys = Object.keys(obj); for (let i = 0, key = keys[i]; i < keys.length; i += 1) { if (Object.hasOwnProperty.call(obj, key)) { return false; } } return true; }; /** * * @param callback callback is any function that needs to limit the number of times it executes. * @param delay delay is the time (in milliseconds) that needs to elapse before callback can execute again. * @returns returns a debounced function */ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type export const debounce = (callback: Function, delay = 0) => { let clearTimer; return function (this: unknown) { // eslint-disable-next-line @typescript-eslint/no-this-alias const context = this; const args = arguments; // eslint-disable-next-line @typescript-eslint/no-unsafe-argument clearTimeout(clearTimer); clearTimer = setTimeout(() => callback.apply(context, args), delay); }; }; /** * * @param obj data that needs to be cloned * @returns cloned value of obj */ export function cloneDeep(obj: unknown) { if (obj === null || typeof obj !== 'object') { return obj; } const clonedObj = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { clonedObj[key] = cloneDeep(obj[key]); } } return clonedObj; } /** * * @param valueA First value * @param valueB Second value * @returns Returns true if both values are equal otherwise false. */ export function isEqual(valueA: unknown, valueB: unknown) { // Check for strict equality first if (valueA === valueB) { return true; } // Check for arrays or objects if (Array.isArray(valueA) && Array.isArray(valueB)) { if (valueA.length !== valueB.length) { return false; } for (let i = 0; i < valueA.length; i++) { if (!isEqual(valueA[i], valueB[i])) { return false; } } return true; } if (typeof valueA === 'object' && typeof valueB === 'object') { const keysA = Object.keys(valueA || {}); const keysB = Object.keys(valueB || {}); if (keysA.length !== keysB.length) { return false; } for (const key of keysA) { if (!isEqual(valueA?.[key], valueB?.[key])) { return false; } } return true; } // For other primitive types, use strict equality return false; } /** * Parses a JSON string into an object of type `T`, where `T` is a record of strings to unknown values. * * @param jsonString The JSON string to parse. * @returns The parsed object, or an empty object of type `T` if the JSON string is invalid. */ export const parseJSON = >(jsonString = ''): T => { try { return JSON.parse(jsonString); } catch (_error) { return {} as T; } }; /** * * @param fieldArray Array of string * @param objectToTraverse Object from which value needs to be extracted * @returns Return field value in a nested object */ export const getNestedField = (fieldArray: unknown, objectToTraverse: unknown): unknown => { const reducerFunction = (accumalator: unknown, current: unknown) => { // @ts-ignore return accumalator && accumalator[current] ? accumalator[current] : null; }; // @ts-ignore return fieldArray.reduce(reducerFunction, objectToTraverse); }; export const getDimensionsFromImageUrl = (url: string, type: 'height' | 'width'): number | undefined => { if (!url) { return; } const regex = { // eslint-disable-next-line no-useless-escape height: /h_(\d+)[,\/]/, // eslint-disable-next-line no-useless-escape width: /w_(\d+)[,\/]/, }; const match = url.match(regex[type]); if (match && match[1]) { return parseInt(match[1], 10); } return; }; export const getHeightFromImgUrl = (url: string): number | undefined => getDimensionsFromImageUrl(url, 'height');