Dotbase-site/contexts/ValidatorContext.tsx

85 lines
2.5 KiB
TypeScript
Raw Permalink Normal View History

2025-02-05 00:07:38 +05:30
'use client';
import { DnDFlowValidationSchema } from '@/utils/zod';
import useDnDStore from '@/stores/useDnDStore';
import _ from 'lodash';
import React from 'react';
import { Node } from 'reactflow';
type ErrorObjType = {
[key: string]: {
[key: string]: string;
};
};
type ValidatorContextType = {
errors: ErrorObjType;
validate: (nds: Node[]) => boolean;
};
export const ValidatorContext = React.createContext<ValidatorContextType>({
errors: {},
validate: () => false,
});
type ModalContextProviderProps = {
children: React.JSX.Element;
};
const ValidatorContextProvider = ({ children }: ModalContextProviderProps) => {
const [errors, setErrors] = React.useState<ErrorObjType>({});
const [prev, setPrev] = React.useState<{ [x: string]: string }[]>();
const [nds, setNds] = React.useState<Node[]>([]);
const { nodes } = useDnDStore();
const _getZodData = React.useCallback((nds: Node[]) => {
return nds.map(({ type, data }) => {
return { [type as string]: data };
});
}, []);
const validate = React.useCallback(
(nds: Node[]): boolean => {
setNds(nds);
try {
setErrors({});
const zodData = _getZodData(nds);
setPrev(zodData);
const zodResults = DnDFlowValidationSchema.safeParse(zodData);
// publish errors to consumers
if (!zodResults.success) {
const issues = zodResults.error.issues;
const updatedErrors: ErrorObjType = {};
issues.forEach(({ path, message }) => {
const nodeIndex = path[0] as number;
const nodeId = nds[nodeIndex].id;
const fieldName = path[path.length - 1];
if (!updatedErrors[nodeId as string]) {
updatedErrors[nodeId as string] = {};
}
updatedErrors[nodeId as string][fieldName as string] = message;
});
setErrors(updatedErrors);
}
return zodResults.success;
} catch (err) {
// toast msg
return true;
}
},
[_getZodData],
);
React.useEffect(() => {
const filteredNodes = nodes.filter((node) => nds?.find((n) => n.id === node.id));
if (prev && !_.isEqual(_getZodData(filteredNodes), prev)) {
// after first submission, now validate the nodes has been validated in onChange event.
validate(filteredNodes);
}
}, [_getZodData, nds, nodes, prev, validate]);
return <ValidatorContext.Provider value={{ errors, validate }}>{children}</ValidatorContext.Provider>;
};
export default ValidatorContextProvider;