import type { Resource } from "@src/tems"; function isValidDateValue(value: unknown): value is string | number | Date { if ( typeof value !== "string" && typeof value !== "number" && !(value instanceof Date) ) { return false; } return !Number.isNaN(new Date(value).getTime()); } const checkValueInIntervalRecursive = ( data: any, propName: string, startValue: number | Date, endValue: number | Date ): boolean => { if (data === null || data === undefined) { return false; } const propPath = propName.split("."); let current = data; for (const segment of propPath) { if (current && typeof current === "object" && segment in current) { current = current[segment]; } else { return false; } } if (typeof current === "number") { if (typeof startValue === "number" && typeof endValue === "number") { if (startValue <= current && current <= endValue) { return true; } } } else if (isValidDateValue(current)) { const date = new Date(current); if (startValue instanceof Date && endValue instanceof Date) { if (startValue <= date && date <= endValue) { return true; } } } else { return false; } if (Array.isArray(data)) { return data.some((item) => checkValueInIntervalRecursive(item, propName, startValue, endValue) ); } if (typeof data === "object") { return Object.entries(data).some(([key, value]) => checkValueInIntervalRecursive(value, propName, startValue, endValue) ); } return false; }; /** * Filters an array of Resource objects based on whether a specific date/number property * falls within a given interval string (e.g., "2023-01-01/2023-01-31" or "3/6"). * Checks the property recursively within nested objects and arrays. */ const filterObjectByDateInterval = ( array: Resource[], propName: string, interval: string ): Resource[] => { if (!propName || !interval || typeof interval !== "string") { return array; } const [startStr, endStr] = interval.split("/"); if (!startStr) { return array; } const startDate = new Date(startStr); const endDate = new Date(endStr ?? startStr); if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) { console.warn(`Invalid date interval provided: ${interval}`); return array; } endDate.setHours(23, 59, 59, 999); if (startDate > endDate) { console.warn(`Start date is after end date in interval: ${interval}`); return array; } return array.filter((obj) => checkValueInIntervalRecursive(obj, propName, startDate, endDate) ); }; const filterObjectByInterval = ( array: Resource[], propName: string, interval: string ): Resource[] => { if (!propName || !interval || typeof interval !== "string") { return array; } const [startStr, endStr] = interval.split("/").map(Number); if (Number.isNaN(startStr) || Number.isNaN(endStr)) { return array; } if (startStr > endStr) { console.warn(`Start number is after end number in interval: ${interval}`); return array; } return array.filter((obj) => checkValueInIntervalRecursive(obj, propName, startStr, endStr) ); }; export default filterObjectByInterval;