import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { MetadataDeleteMap, MetadataType } from '../hooks/use-manage-modal'; import { IManageValuesProps, IMetaDataTableData } from '../interface'; export const useManageValues = (props: IManageValuesProps) => { const { data, isShowValueSwitch, hideModal, onSave, addUpdateValue, addDeleteValue, existsKeys, type, } = props; const { t } = useTranslation(); const [metaData, setMetaData] = useState(data); const [valueError, setValueError] = useState>({ field: '', values: '', }); const [deleteDialogContent, setDeleteDialogContent] = useState({ visible: false, title: '', name: '', warnText: '', onOk: () => {}, onCancel: () => {}, }); const hideDeleteModal = () => { setDeleteDialogContent({ visible: false, title: '', name: '', warnText: '', onOk: () => {}, onCancel: () => {}, }); }; // Use functional update to avoid closure issues const handleChange = useCallback( (field: string, value: any) => { if (field === 'field' && existsKeys.includes(value)) { setValueError((prev) => { return { ...prev, field: type === MetadataType.Setting ? t('knowledgeDetails.metadata.fieldExists') : t('knowledgeDetails.metadata.fieldNameExists'), }; }); } else if (field === 'field' && !existsKeys.includes(value)) { setValueError((prev) => { return { ...prev, field: '', }; }); } setMetaData((prev) => ({ ...prev, [field]: value, })); }, [existsKeys, type, t], ); // Maintain separate state for each input box const [tempValues, setTempValues] = useState([...data.values]); useEffect(() => { setTempValues([...data.values]); setMetaData(data); }, [data]); const handleHideModal = useCallback(() => { hideModal(); setMetaData({} as IMetaDataTableData); }, [hideModal]); const handleSave = useCallback(() => { if (type === MetadataType.Setting && valueError.field) { return; } if (!metaData.restrictDefinedValues && isShowValueSwitch) { const newMetaData = { ...metaData, values: [] }; onSave(newMetaData); } else { onSave(metaData); } handleHideModal(); }, [metaData, onSave, handleHideModal, isShowValueSwitch, type, valueError]); // Handle value changes, only update temporary state const handleValueChange = useCallback( (index: number, value: string) => { setTempValues((prev) => { if (prev.includes(value)) { setValueError((prev) => { return { ...prev, values: t('knowledgeDetails.metadata.valueExists'), }; }); } else { setValueError((prev) => { return { ...prev, values: '', }; }); } const newValues = [...prev]; newValues[index] = value; return newValues; }); }, [t], ); // Handle blur event, synchronize to main state const handleValueBlur = useCallback(() => { // addUpdateValue(metaData.field, [...new Set([...tempValues])]); tempValues.forEach((newValue, index) => { if (index < data.values.length) { const originalValue = data.values[index]; if (originalValue !== newValue) { addUpdateValue(metaData.field, originalValue, newValue); } } else { if (newValue) { addUpdateValue(metaData.field, '', newValue); } } }); handleChange('values', [...new Set([...tempValues])]); }, [handleChange, tempValues, metaData, data, addUpdateValue]); // Handle delete operation const handleDelete = useCallback( (index: number) => { setTempValues((prev) => { const newTempValues = [...prev]; addDeleteValue(metaData.field, newTempValues[index]); newTempValues.splice(index, 1); return newTempValues; }); // Synchronize to main state setMetaData((prev) => { const newMetaDataValues = [...prev.values]; newMetaDataValues.splice(index, 1); return { ...prev, values: newMetaDataValues, }; }); }, [addDeleteValue, metaData], ); const showDeleteModal = (item: string, callback: () => void) => { setDeleteDialogContent({ visible: true, title: t('common.delete') + ' ' + t('knowledgeDetails.metadata.value'), name: item, warnText: MetadataDeleteMap(t)[type as MetadataType].warnValueText, onOk: () => { hideDeleteModal(); callback(); }, onCancel: () => { hideDeleteModal(); }, }); }; // Handle adding new value const handleAddValue = useCallback(() => { setTempValues((prev) => [...new Set([...prev, ''])]); // Synchronize to main state setMetaData((prev) => ({ ...prev, values: [...new Set([...prev.values, ''])], })); }, []); return { metaData, tempValues, valueError, deleteDialogContent, handleChange, handleValueChange, handleValueBlur, handleDelete, handleAddValue, showDeleteModal, handleSave, handleHideModal, }; };