import React, { useEffect, useState, useCallback } from "react"; import { Tree } from "antd"; import type { DataNode, TreeProps } from "antd/es/tree"; import { getUniqueItems } from "@nice/common"; import { api } from "@nice/client"; interface TermData { value?: string; children?: TermData[]; key?: string; hasChildren?: boolean; isLeaf?: boolean; pId?: string; title?: React.ReactNode; data?: any; order?: string; id?: string; } interface TermTreeProps { defaultValue?: string | string[]; value?: string | string[]; onChange?: (value: string | string[]) => void; multiple?: boolean; taxonomyId?: string; disabled?: boolean; className?: string; domainId?: string; style?: React.CSSProperties; } const TermTree: React.FC = ({ defaultValue, value, onChange, className, multiple = false, taxonomyId, domainId, disabled = false, style, }) => { const utils = api.useUtils(); const [treeData, setTreeData] = useState([]); const processTermData = (terms: TermData[]): TermData[] => { return terms.map((term) => ({ ...term, key: term.key || term.id || "", title: term.title || term.value, children: term.children ? processTermData(term.children) : undefined, })); }; const fetchParentTerms = useCallback( async (termIds: string | string[], taxonomyId?: string) => { const idsArray = Array.isArray(termIds) ? termIds : [termIds].filter(Boolean); try { const result = await utils.term.getParentSimpleTree.fetch({ termIds: idsArray, taxonomyId, domainId, }); return processTermData(result); } catch (error) { console.error( "Error fetching parent terms for termIds", idsArray, ":", error ); throw error; } }, [utils, domainId] ); const fetchTerms = useCallback(async () => { try { const rootTerms = await utils.term.getChildSimpleTree.fetch({ taxonomyId, domainId, }); let combinedTerms = processTermData(rootTerms); if (defaultValue) { const defaultTerms = await fetchParentTerms( defaultValue, taxonomyId ); combinedTerms = getUniqueItems( [...treeData, ...combinedTerms, ...defaultTerms], "key" ); } if (value) { const valueTerms = await fetchParentTerms(value, taxonomyId); combinedTerms = getUniqueItems( [...treeData, ...combinedTerms, ...valueTerms], "key" ); } setTreeData(combinedTerms); } catch (error) { console.error("Error fetching terms:", error); } }, [ defaultValue, value, taxonomyId, utils, fetchParentTerms, domainId, treeData, ]); useEffect(() => { fetchTerms(); }, [fetchTerms]); const onLoadData = async ({ key }: any) => { try { const result = await utils.term.getChildSimpleTree.fetch({ termIds: [key], taxonomyId, domainId, }); const processedResult = processTermData(result); const newItems = getUniqueItems( [...treeData, ...processedResult], "key" ); setTreeData(newItems); } catch (error) { console.error( "Error loading data for node with key", key, ":", error ); } }; const handleCheck: TreeProps["onCheck"] = (checkedKeys, info) => { if (onChange) { if (multiple) { onChange(checkedKeys as string[]); } else { onChange((checkedKeys as string[])[0] || ""); } } }; const handleExpand = async (expandedKeys: React.Key[]) => { try { const allKeyIds = expandedKeys .map((key) => key.toString()) .filter(Boolean); const expandedNodes = await utils.term.getChildSimpleTree.fetch({ termIds: allKeyIds, taxonomyId, domainId, }); const processedNodes = processTermData(expandedNodes); const newItems = getUniqueItems( [...treeData, ...processedNodes], "key" ); setTreeData(newItems); } catch (error) { console.error( "Error expanding nodes with keys", expandedKeys, ":", error ); } }; return ( ); }; export default TermTree;