import { useState, useEffect, useMemo } from 'react'; import { FieldSpec } from '@digigov/form/types'; import { ScalarType } from '@digigov/react-modules/FilteredResults'; export function isBooleanString(str: string): boolean { return /^(true|false)$/i.test(str); } export function normalizeText(text: string): string { return text.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } export const getOptionLabelForSelectValue = (field, value) => { if (field.extra?.options) { const matchedOption = field.extra.options.find( (option) => option.value.toString() === value?.toString() ); if (matchedOption) { return matchedOption.label.primary; } } return value; }; export const useURLParamsSearch = (searchFunc, { navigate, fields }) => { const urlParams = new URLSearchParams(window.location.search); const currentParams = Object.fromEntries(urlParams.entries()); const values = fields.reduce((newValues, field) => { if (currentParams[field.key]) { newValues[field.key] = currentParams[field.key]; } return newValues; }, {}); const search = (params) => { navigate( '?' + new URLSearchParams( // @ts-ignore Object.entries({ ...currentParams, ...params }).filter( ([, value]) => !!value ) ).toString() ); return searchFunc(params); }; return { search, values }; }; interface UseStaticSearchProps< DT extends Record, FT extends Record, > { fields: FieldSpec[]; data: DT[]; initialFilters: FT; } export function useStaticSearch< DT extends Record, FT extends Record, >({ fields, data, initialFilters }: UseStaticSearchProps) { const [results, setResults] = useState(data); useEffect(() => { search(initialFilters); }, [initialFilters]); const search = (filters: FT) => { if (!filters || Object.keys(filters).every((key) => filters[key] === '')) { setResults(data); return; } const newResults = data.filter((row) => { const filterKeys = Object.keys(filters); const enabledFilters = filterKeys.filter( (filterKey) => filters[filterKey]?.toString() && row[filterKey]?.toString() ); const freeTextFilters = filterKeys.filter( (filterKey) => filters[filterKey]?.toString() && !row[filterKey]?.toString() ); let filtersMatchingValue = false; // Filter the fields that exists as columns in table if (enabledFilters.length > 0) { filtersMatchingValue = enabledFilters.every((filterKey) => { if (filters[filterKey]?.toString() !== row[filterKey]?.toString()) { const field = fields.find((f) => f.key === filterKey); const optionsObj = field?.extra?.options.find( (option) => option?.label?.primary === row[filterKey] ); return ( optionsObj?.value.toString() === filters[filterKey]?.toString() ); } filtersMatchingValue = true; return filtersMatchingValue; }); if (!filtersMatchingValue) { return false; } } // Filter the free text fields (doesn't exist as columns) if (freeTextFilters.length > 0) { return freeTextFilters.every((filterKey) => { return Object.values(row).some((value) => { if (typeof value !== 'string') { return false; } const normalizedItemValue = normalizeText( value.toString().toLowerCase() ); const normalizedFilterValue = normalizeText( filters[filterKey]?.toString().toLowerCase().trim() || '' ); return normalizedItemValue.includes(normalizedFilterValue); }); }); } return filtersMatchingValue; }); setResults(newResults); }; return useMemo(() => ({ search, results }), [search, results]); }