From c78e0980a82afe14245a4dc0a732b6769face39b Mon Sep 17 00:00:00 2001 From: Mohammer5 Date: Tue, 27 Feb 2024 17:34:07 +0800 Subject: [PATCH] refactor: dry up form validation & zod segmentsToPath --- src/lib/form/index.ts | 1 + src/lib/form/validate.ts | 22 ++++++++++++++++ src/lib/index.ts | 1 + src/lib/zod/index.ts | 1 + src/lib/zod/segmentsToPath.ts | 8 ++++++ src/pages/dataElementGroups/Edit.tsx | 8 +++--- src/pages/dataElementGroups/New.tsx | 8 +++--- src/pages/dataElementGroups/form/index.ts | 2 +- src/pages/dataElementGroups/form/validate.ts | 27 -------------------- src/pages/dataElements/Edit.tsx | 8 +++--- src/pages/dataElements/New.tsx | 13 +++++++--- src/pages/dataElements/form/index.ts | 2 +- src/pages/dataElements/form/validate.ts | 27 -------------------- 13 files changed, 60 insertions(+), 68 deletions(-) create mode 100644 src/lib/form/validate.ts create mode 100644 src/lib/zod/index.ts create mode 100644 src/lib/zod/segmentsToPath.ts delete mode 100644 src/pages/dataElementGroups/form/validate.ts delete mode 100644 src/pages/dataElements/form/validate.ts diff --git a/src/lib/form/index.ts b/src/lib/form/index.ts index 5f5121a0..cc2fdd0c 100644 --- a/src/lib/form/index.ts +++ b/src/lib/form/index.ts @@ -1,3 +1,4 @@ export { composeAsyncValidators } from './composeAsyncValidators' export type { FormFieldValidator } from './composeAsyncValidators' export { required } from './validators' +export { validate } from './validate' diff --git a/src/lib/form/validate.ts b/src/lib/form/validate.ts new file mode 100644 index 00000000..c1c1aa58 --- /dev/null +++ b/src/lib/form/validate.ts @@ -0,0 +1,22 @@ +import { setIn } from 'final-form' +import { z } from 'zod' +import { segmentsToPath } from '../zod' + +export function validate( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + zodSchema: z.ZodType, + values: FormValues +) { + const zodResult = zodSchema.safeParse(values) + + if (zodResult.success !== false) { + return undefined + } + + const allFormErrors = zodResult.error.issues.reduce((formErrors, error) => { + const errorPath = segmentsToPath(error.path) + return setIn(formErrors, errorPath, error.message) + }, {}) + + return allFormErrors +} diff --git a/src/lib/index.ts b/src/lib/index.ts index c0b484aa..a4273fdd 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -16,3 +16,4 @@ export * from './date' export * from './systemSettings' // export * from './utils' export * from './dataStore' +export * from './zod' diff --git a/src/lib/zod/index.ts b/src/lib/zod/index.ts new file mode 100644 index 00000000..4d3fa136 --- /dev/null +++ b/src/lib/zod/index.ts @@ -0,0 +1 @@ +export { segmentsToPath } from './segmentsToPath' diff --git a/src/lib/zod/segmentsToPath.ts b/src/lib/zod/segmentsToPath.ts new file mode 100644 index 00000000..21821fc5 --- /dev/null +++ b/src/lib/zod/segmentsToPath.ts @@ -0,0 +1,8 @@ +// @TODO: Figure out if there's a utility for this? I couldn't find one +export function segmentsToPath(segments: Array) { + return segments.reduce((path, segment) => { + return typeof segment === 'number' + ? `${path}[${segment}]` + : `${path}.${segment}` + }) as string +} diff --git a/src/pages/dataElementGroups/Edit.tsx b/src/pages/dataElementGroups/Edit.tsx index e8c88889..f506ac4c 100644 --- a/src/pages/dataElementGroups/Edit.tsx +++ b/src/pages/dataElementGroups/Edit.tsx @@ -10,12 +10,12 @@ import { StandardFormActions, StandardFormSection, } from '../../components' -import { SCHEMA_SECTIONS, getSectionPath } from '../../lib' +import { SCHEMA_SECTIONS, getSectionPath, validate } from '../../lib' import { JsonPatchOperation } from '../../types' import { DataElementGroup } from '../../types/generated' import { createJsonPatchOperations } from './edit/' import classes from './Edit.module.css' -import { DataElementGroupFormFields, validate } from './form' +import { DataElementGroupFormFields, dataElementGroupSchema } from './form' import type { FormValues } from './form' type FinalFormFormApi = FormApi @@ -125,7 +125,9 @@ export const Component = () => {
{ + return validate(dataElementGroupSchema, values) + }} initialValues={initialValues} > {({ handleSubmit, submitting, submitError }) => ( diff --git a/src/pages/dataElementGroups/New.tsx b/src/pages/dataElementGroups/New.tsx index 7b08af8f..31b4633a 100644 --- a/src/pages/dataElementGroups/New.tsx +++ b/src/pages/dataElementGroups/New.tsx @@ -6,8 +6,8 @@ import React, { useEffect, useRef } from 'react' import { Form } from 'react-final-form' import { useNavigate } from 'react-router-dom' import { StandardFormActions, StandardFormSection } from '../../components' -import { SCHEMA_SECTIONS, getSectionPath } from '../../lib' -import { DataElementGroupFormFields, validate } from './form' +import { SCHEMA_SECTIONS, getSectionPath, validate } from '../../lib' +import { DataElementGroupFormFields, dataElementGroupSchema } from './form' import type { FormValues } from './form' import classes from './New.module.css' @@ -50,7 +50,9 @@ export function Component() { { + return validate(dataElementGroupSchema, values) + }} initialValues={initialValues} > {({ handleSubmit, submitting, submitError }) => ( diff --git a/src/pages/dataElementGroups/form/index.ts b/src/pages/dataElementGroups/form/index.ts index e1ecc676..17ffd2ad 100644 --- a/src/pages/dataElementGroups/form/index.ts +++ b/src/pages/dataElementGroups/form/index.ts @@ -1,3 +1,3 @@ export { DataElementGroupFormFields } from './DataElementGroupFormFields' +export { dataElementGroupSchema } from './dataElementGroupSchema' export type { FormValues } from './types' -export { validate } from './validate' diff --git a/src/pages/dataElementGroups/form/validate.ts b/src/pages/dataElementGroups/form/validate.ts deleted file mode 100644 index b9b9fcd5..00000000 --- a/src/pages/dataElementGroups/form/validate.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { setIn } from 'final-form' -import { dataElementGroupSchema } from './dataElementGroupSchema' -import type { FormValues } from './types' - -// @TODO: Figure out if there's a utility for this? I couldn't find one -function segmentsToPath(segments: Array) { - return segments.reduce((path, segment) => { - return typeof segment === 'number' - ? `${path}[${segment}]` - : `${path}.${segment}` - }) as string -} - -export function validate(values: FormValues) { - const zodResult = dataElementGroupSchema.safeParse(values) - - if (zodResult.success !== false) { - return undefined - } - - const allFormErrors = zodResult.error.issues.reduce((formErrors, error) => { - const errorPath = segmentsToPath(error.path) - return setIn(formErrors, errorPath, error.message) - }, {}) - - return allFormErrors -} diff --git a/src/pages/dataElements/Edit.tsx b/src/pages/dataElements/Edit.tsx index b4889306..31fdb2dd 100644 --- a/src/pages/dataElements/Edit.tsx +++ b/src/pages/dataElements/Edit.tsx @@ -10,13 +10,13 @@ import { StandardFormActions, StandardFormSection, } from '../../components' -import { SCHEMA_SECTIONS, getSectionPath } from '../../lib' +import { SCHEMA_SECTIONS, getSectionPath, validate } from '../../lib' import { JsonPatchOperation } from '../../types' import { Attribute, DataElement } from '../../types/generated' import { createJsonPatchOperations } from './edit/' import classes from './Edit.module.css' import { useCustomAttributesQuery } from './fields' -import { DataElementFormFields, validate } from './form' +import { DataElementFormFields, dataElementSchema } from './form' import type { FormValues } from './form' type FinalFormFormApi = FormApi @@ -174,7 +174,9 @@ export const Component = () => { { + return validate(dataElementSchema, values) + }} initialValues={initialValues} > {({ handleSubmit, submitting, submitError }) => ( diff --git a/src/pages/dataElements/New.tsx b/src/pages/dataElements/New.tsx index a97b3d3a..a55e972e 100644 --- a/src/pages/dataElements/New.tsx +++ b/src/pages/dataElements/New.tsx @@ -10,10 +10,15 @@ import { StandardFormActions, StandardFormSection, } from '../../components' -import { SCHEMA_SECTIONS, getSectionPath, useSchemas } from '../../lib' +import { + SCHEMA_SECTIONS, + getSectionPath, + useSchemas, + validate, +} from '../../lib' import { Attribute } from '../../types/generated' import { useCustomAttributesQuery } from './fields' -import { DataElementFormFields, validate } from './form' +import { DataElementFormFields, dataElementSchema } from './form' import type { FormValues } from './form' import classes from './New.module.css' @@ -142,7 +147,9 @@ export const Component = () => { { + return validate(dataElementSchema, values) + }} initialValues={initialValues} > {({ handleSubmit, submitting, submitError }) => ( diff --git a/src/pages/dataElements/form/index.ts b/src/pages/dataElements/form/index.ts index 27f586c5..31831a4c 100644 --- a/src/pages/dataElements/form/index.ts +++ b/src/pages/dataElements/form/index.ts @@ -1,3 +1,3 @@ export { DataElementFormFields } from './DataElementFormFields' +export { dataElementSchema } from './dataElementSchema' export type { FormValues } from './types' -export { validate } from './validate' diff --git a/src/pages/dataElements/form/validate.ts b/src/pages/dataElements/form/validate.ts deleted file mode 100644 index c43b370a..00000000 --- a/src/pages/dataElements/form/validate.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { setIn } from 'final-form' -import { dataElementSchema } from './dataElementSchema' -import type { FormValues } from './types' - -// @TODO: Figure out if there's a utility for this? I couldn't find one -function segmentsToPath(segments: Array) { - return segments.reduce((path, segment) => { - return typeof segment === 'number' - ? `${path}[${segment}]` - : `${path}.${segment}` - }) as string -} - -export function validate(values: FormValues) { - const zodResult = dataElementSchema.safeParse(values) - - if (zodResult.success !== false) { - return undefined - } - - const allFormErrors = zodResult.error.issues.reduce((formErrors, error) => { - const errorPath = segmentsToPath(error.path) - return setIn(formErrors, errorPath, error.message) - }, {}) - - return allFormErrors -}