import type { Resource } from "@src/tems"; const calculatePertinenceScoreRecursive = ( data: any, lowerCaseString: string, isTargetProperty: boolean ): number => { if (data === null || data === undefined) { return 0; } if (typeof data !== "object") { if (!isTargetProperty) { return 0; } const valueString = String(data).toLowerCase(); const escapedString = lowerCaseString.replace( /[.*+?^${}()|[\]\\]/g, "\\$&" ); const wholeWordRegex = new RegExp(`\\b${escapedString}\\b`); let score = 0; if (wholeWordRegex.test(valueString)) { score = 2; } else if (valueString.includes(lowerCaseString)) { score = 1; } return score; } if (Array.isArray(data)) { let maxScore = 0; for (const item of data) { maxScore = Math.max( maxScore, calculatePertinenceScoreRecursive( item, lowerCaseString, isTargetProperty ) ); if (maxScore === 2) break; } return maxScore; } let maxScore = 0; for (const value of Object.values(data)) { maxScore = Math.max( maxScore, calculatePertinenceScoreRecursive( value, lowerCaseString, isTargetProperty ) ); if (maxScore === 2) break; } return maxScore; }; const filterObjectByNamedValue = ( array: Resource[], propName: string, searchString: string ): Resource[] => { if (!propName || !searchString || searchString.trim() === "") { return array; } const lowerCaseString = searchString.toLowerCase(); const scoredObjects = array.map((obj) => { let current: any = obj; const propPath = propName.split("."); for (const segment of propPath) { if (current && typeof current === "object" && segment in current) { current = current[segment]; } else { current = null; break; } } let score = 0; if (current) { score = calculatePertinenceScoreRecursive(current, lowerCaseString, true); } return { obj, score }; }); const filteredObjects = scoredObjects.filter((item) => item.score > 0); filteredObjects.sort((a, b) => b.score - a.score); return filteredObjects.map((item) => item.obj); }; export default filterObjectByNamedValue;