import { useEffect, useState } from "react"; import { useApiRequest } from "../../utils/useApiRequest"; import AutoComplete from "../AutoComplete/AutoComplete"; import { getFaPermissions } from "../../utils/getFaPermissions"; import { getNestedValue } from "../../utils/getNestedValue"; type FormEnterLocationsProps = { title: string; api: string; error?: boolean; errorMessage?: any; multiple?: boolean; onChange?: (data: any) => void; onChangeValue?: (data: any) => void; keyField?: string; secondaryKey?: string | string[]; tertiaryKey?: string | string[]; valueField?: string | string[]; valueField2?: string | string[]; valueField3?: string | string[]; filterAddress?: string[]; filterValue?: string[]; defaultKey?: string | number | any[]; valueTemplate?: string; valueTemplateProps?: Array<{ [key: string]: "string" | "number" }>; groupBy?: string | string[]; groupFunction?: (item: any) => string; selectField?: boolean; }; export const FormApiBasedAutoComplete = ({ title, api, error, errorMessage, onChange, onChangeValue, keyField = "id", secondaryKey, tertiaryKey, valueField = "name", valueField2, valueField3, defaultKey, multiple = false, filterValue, filterAddress, valueTemplate, valueTemplateProps, groupBy, groupFunction, selectField = false, }: FormEnterLocationsProps) => { const [data, setData] = useState([]); const [selectedKeys, setSelectedKeys] = useState<(string | number)[]>([]); const [groupedItemsMap, setGroupedItemsMap] = useState< Map >(new Map()); const formatValue = (value: any, fieldKey: string) => { if (!valueTemplate || !valueTemplateProps) return value; const templateProp = valueTemplateProps.find((prop) => prop[fieldKey]); if (!templateProp) return value; const fieldType = templateProp[fieldKey]; if (fieldType === "number") { const numValue = typeof value === "number" ? value : Number(value); return !isNaN(numValue) ? numValue.toLocaleString() : String(value); } else if (fieldType === "string") { let result = String(value); if (typeof value === "string" && value.includes(",")) { result = value.replace(/,/g, ""); } return result; } return value; }; const { data: apiData } = useApiRequest({ api: api, method: "get", params: { page: 1, page_size: 1000 }, queryKey: [api], disableBackdrop: defaultKey ? true : false, }); useEffect(() => { if (apiData?.results) { let data; if (filterAddress && filterValue) { data = apiData.results?.filter( (item: any) => !filterValue.includes(getNestedValue(item, filterAddress)) ); } else { data = apiData.results; } const d = data?.map((option: any) => ({ key: option[keyField], secondaryKey: secondaryKey ? typeof secondaryKey === "string" ? option[secondaryKey] : getNestedValue(option, secondaryKey) : undefined, tertiaryKey: tertiaryKey ? typeof tertiaryKey === "string" ? option[tertiaryKey] : getNestedValue(option, tertiaryKey) : undefined, value: valueTemplate ? valueTemplate .replace( /v1/g, formatValue( valueField === "page" ? getFaPermissions(option[valueField]) : typeof valueField === "string" ? option[valueField] : getNestedValue(option, valueField), "v1" ) ) .replace( /v2/g, formatValue( valueField2 ? typeof valueField2 === "string" ? option[valueField2] : getNestedValue(option, valueField2) : "", "v2" ) ) .replace( /v3/g, formatValue( valueField3 ? typeof valueField3 === "string" ? option[valueField3] : getNestedValue(option, valueField3) : "", "v3" ) ) : `${ valueField === "page" ? getFaPermissions(option[valueField]) : typeof valueField === "string" ? option[valueField] : getNestedValue(option, valueField) } ${ valueField2 ? " - " + (typeof valueField2 === "string" ? option[valueField2] : getNestedValue(option, valueField2)) : "" } ${ valueField3 ? "(" + (typeof valueField3 === "string" ? option[valueField3] : getNestedValue(option, valueField3)) + ")" : "" }`, groupValue: groupBy ? typeof groupBy === "string" ? option[groupBy] : getNestedValue(option, groupBy) : undefined, })); let finalData = d; if (groupBy) { const grouped = new Map(); d.forEach((item: any) => { const groupKey = item.groupValue ?? ""; if (!grouped.has(groupKey)) { grouped.set(groupKey, []); } grouped.get(groupKey)!.push(item); }); setGroupedItemsMap(grouped); finalData = []; grouped.forEach((items, groupKey) => { finalData.push({ key: `__group__${groupKey}`, value: groupFunction ? groupFunction(groupKey) : String(groupKey), disabled: true, isGroupHeader: true, originalGroupKey: groupKey, }); finalData.push(...items); }); } else { setGroupedItemsMap(new Map()); } setData(finalData); const actualDataItems = finalData.filter( (item: any) => !item.isGroupHeader && !item.disabled ); if (defaultKey !== undefined && defaultKey !== null) { if (multiple) { if (Array.isArray(defaultKey)) { if (defaultKey.length === 0) { setSelectedKeys([]); } else { const defaultIds = defaultKey.map((item: any) => typeof item === "object" ? item[keyField] : item ); const defaultItems = actualDataItems.filter((item: any) => defaultIds.includes(item.key) ); setSelectedKeys(defaultItems.map((item: any) => item.key)); if (onChange) { if (secondaryKey) { console.log("dksk0", defaultItems); onChange( defaultItems.map((item: any) => { return { key: item?.key, key2: item?.secondaryKey, ...(tertiaryKey ? { key3: item?.tertiaryKey, } : {}), }; }) ); if (onChangeValue) { onChangeValue( defaultItems.map((item: any) => item.value.trim()) ); } } else { onChange(defaultItems.map((item: any) => item.key)); } } } } } else { if (!Array.isArray(defaultKey)) { const keyToFind = typeof defaultKey === "object" ? defaultKey[keyField] : defaultKey; const defaultItem = actualDataItems.find( (item: any) => item.key === keyToFind ); if (defaultItem) { setSelectedKeys([keyToFind]); if (onChange) { if (secondaryKey) { onChange({ key1: defaultItem.key, key2: defaultItem.secondaryKey, ...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}), }); } else { onChange(keyToFind); } } if (onChangeValue) { onChangeValue({ key1: defaultItem.key, key2: defaultItem.secondaryKey, ...(tertiaryKey ? { key3: defaultItem.tertiaryKey } : {}), value: defaultItem.value.trim(), }); } } } } } } }, [apiData]); const handleGroupHeaderClick = (groupKey: string | number) => { if (!multiple || !groupBy) return; const groupItems = groupedItemsMap.get(groupKey) || []; if (groupItems.length === 0) return; const groupItemKeys = groupItems.map((item: any) => item.key); const allGroupItemsSelected = groupItemKeys.every((key) => selectedKeys.includes(key) ); let newSelectedKeys: (string | number)[]; if (allGroupItemsSelected) { newSelectedKeys = selectedKeys.filter( (key) => !groupItemKeys.includes(key) ); } else { const newKeys = groupItemKeys.filter( (key) => !selectedKeys.includes(key) ); newSelectedKeys = [...selectedKeys, ...newKeys]; } setSelectedKeys(newSelectedKeys); if (!onChange) return; const selectedItems = data.filter( (item: any) => newSelectedKeys.includes(item.key) && !item.isGroupHeader && !item.disabled ); if (secondaryKey) { onChange( selectedItems.map((item: any) => ({ key1: item.key, key2: item.secondaryKey, ...(tertiaryKey ? { key3: item.tertiaryKey } : {}), })) ); if (onChangeValue) { onChangeValue(selectedItems.map((item: any) => item.value.trim())); } } else { onChange(newSelectedKeys); } }; return ( <> { setSelectedKeys(newSelectedKeys); if (!onChange) return; if (multiple) { if (secondaryKey) { const selectedItems = data.filter( (item: any) => newSelectedKeys.includes(item.key) && !item.isGroupHeader && !item.disabled ); onChange( selectedItems.map((item: any) => ({ key1: item.key, key2: item.secondaryKey, ...(tertiaryKey ? { key3: item.tertiaryKey } : {}), })) ); if (onChangeValue) { onChangeValue( selectedItems.map((item: any) => item.value.trim()) ); } } else { const validKeys = newSelectedKeys.filter( (key) => !String(key).startsWith("__group__") ); onChange(validKeys); } } else { if (secondaryKey) { const selectedItem = data.find( (item: any) => item.key === newSelectedKeys[0] && !item.isGroupHeader && !item.disabled ); if (onChangeValue) { onChangeValue({ value: selectedItem?.value.trim() ?? "", key1: selectedItem?.key ?? "", key2: selectedItem?.secondaryKey ?? "", ...(tertiaryKey ? { key3: selectedItem?.tertiaryKey ?? "" } : {}), }); } if (selectedItem) { onChange({ key1: selectedItem.key, key2: selectedItem.secondaryKey, ...(tertiaryKey ? { key3: selectedItem.tertiaryKey } : {}), }); } } else { const validKey = newSelectedKeys[0] && !String(newSelectedKeys[0]).startsWith("__group__") ? newSelectedKeys[0] : ""; onChange(validKey); } } }} title={title} error={error} helperText={errorMessage} onGroupHeaderClick={handleGroupHeaderClick} /> ); };