import { yupResolver } from '@hookform/resolvers/yup'; import type { PanelsPreferences, Workspace } from '@zakodium/nmrium-core'; import type { Ref } from 'react'; import { forwardRef, memo, useCallback, useImperativeHandle, useMemo, } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import * as Yup from 'yup'; import { useChartData } from '../../context/ChartContext.js'; import { usePreferences } from '../../context/PreferencesContext.js'; import type { GroupPaneStyle } from '../../elements/GroupPane.js'; import { GroupPane } from '../../elements/GroupPane.js'; import { Scroller } from '../../elements/Scroller.js'; import useNucleus from '../../hooks/useNucleus.js'; import { usePanelPreferencesByNuclei } from '../../hooks/usePanelPreferences.js'; import { getSpectraObjectPaths } from '../../utility/getSpectraObjectPaths.js'; import { replaceNucleiObjectKeys } from '../../utility/replaceNucleiObjectKeys.js'; import { NucleusGroup } from '../extra/preferences/NucleusGroup.js'; import { PreferencesContainer } from '../extra/preferences/PreferencesContainer.js'; import { SpectraColumnsManager } from './base/SpectraColumnsManager.js'; const groupPaneStyle: GroupPaneStyle = { header: { color: 'black', fontSize: '12px', padding: '5px', backgroundColor: '#f8f8f8', }, container: { paddingBottom: '10px', }, }; function validationColumns(obj: any) { const validationObject: Record = {}; for (const key of Object.keys(obj.nuclei)) { validationObject[key] = Yup.object({ columns: Yup.array().of( Yup.object().shape( { jpath: Yup.array().when('jpath', { is: (jpath: any) => { return jpath !== undefined; }, // eslint-disable-next-line unicorn/no-thenable then: () => Yup.array().of(Yup.string()).required().min(1), }), }, [['jpath', 'jpath']], ), ), }); } return validationObject; } const spectraPreferencesValidation: any = Yup.lazy( (obj: Workspace['panels']['spectra']) => Yup.object().shape({ nuclei: Yup.object().shape(validationColumns(obj)), }), ); function SpectraPreferences(props: object, ref: Ref) { const { data, view: { spectra: { activeTab }, }, } = useChartData(); const preferences = usePreferences(); const nuclei = useNucleus(); const preferencesByNuclei = usePanelPreferencesByNuclei('spectra', nuclei); const methods = useForm({ defaultValues: replaceNucleiObjectKeys(preferencesByNuclei, ',', '_'), resolver: yupResolver(spectraPreferencesValidation), }); const { handleSubmit, getValues, reset, formState: { isValid }, } = methods; const { datalist, paths } = useMemo( () => getSpectraObjectPaths(data), [data], ); const saveHandler = useCallback( (values: any) => { preferences.dispatch({ type: 'SET_PANELS_PREFERENCES', payload: { key: 'spectra', value: replaceNucleiObjectKeys(values, '_', ','), }, }); return true; }, [preferences], ); useImperativeHandle( ref, () => ({ saveSetting: () => { void handleSubmit(saveHandler)(); return isValid; }, }), [handleSubmit, isValid, saveHandler], ); const handleAdd = useCallback( (nucleus: string, index: number) => { const data: PanelsPreferences['spectra'] = getValues(); let columns = data.nuclei[nucleus]?.columns || []; columns = [ ...columns.slice(0, index), { jpath: [], label: '', visible: true, }, ...columns.slice(index), ]; reset({ ...data, nuclei: { ...data.nuclei, [nucleus]: { ...data.nuclei[nucleus], columns, }, }, }); }, [getValues, reset], ); const handleDelete = useCallback( (nucleus: any, index: any) => { const data: PanelsPreferences['spectra'] = getValues(); const columns = data.nuclei[nucleus]?.columns.filter( (_, columnIndex) => columnIndex !== index, ); reset({ ...data, nuclei: { ...data.nuclei, [nucleus]: { ...data.nuclei[nucleus], columns, }, }, }); }, [getValues, reset], ); const mapOnChangeValueHandler = useCallback( (key: any) => { const path = (paths as any)[key]; if (path) { return path; } return key || ' '; }, [paths], ); return ( {nuclei?.map((n) => ( ))} ); } export default memo(forwardRef(SpectraPreferences));