From 05990f028b266ad0b6dcc8ac0f981d1ea8fb6940 Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Wed, 15 Nov 2023 13:39:26 +0300 Subject: [PATCH] apps/web: add form store api/ius: add validate function --- apps/web/api/ius/query.ts | 11 +++++++++ apps/web/api/ius/types.ts | 9 +++++-- apps/web/components/Form/Buttons.tsx | 14 ++++++++++- apps/web/components/Form/Elements.tsx | 21 ++++++++++++----- apps/web/package.json | 3 ++- apps/web/store/ius/form.ts | 34 +++++++++++++++++++++++++++ yarn.lock | 12 ++++++++++ 7 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 apps/web/store/ius/form.ts diff --git a/apps/web/api/ius/query.ts b/apps/web/api/ius/query.ts index aa49f35..b4f7282 100644 --- a/apps/web/api/ius/query.ts +++ b/apps/web/api/ius/query.ts @@ -1,5 +1,6 @@ import type * as t from './types'; import { urls } from '@/config/urls'; +import type { WretchError } from 'wretch'; import wretch from 'wretch'; const api = wretch(urls.URL_UIS).errorType('json'); @@ -41,3 +42,13 @@ export async function getConditions(createUrl: CreateUrl) { .res((res) => res.text()) .then((res) => res); } + +export async function validate(createUrl: CreateUrl) { + const url = createUrl('/validate'); + + return api + .post(url) + .res((res) => res.ok) + .then((res) => res) + .catch((error: WretchError) => error.json as t.HttpValidationError); +} diff --git a/apps/web/api/ius/types.ts b/apps/web/api/ius/types.ts index 3076dea..ccc1a59 100644 --- a/apps/web/api/ius/types.ts +++ b/apps/web/api/ius/types.ts @@ -9,8 +9,9 @@ export type MetaObject = { visible: boolean; }; -export type Request = { searchParams: any; slug: string }; -export type ResponseGetData = Record; +type Value = string | number | string[] | undefined; + +export type ResponseGetData = Record; export type ResponseMetaData = Record; export type ResponseConfig = { title: string }; export type ResponseConditions = string; @@ -20,3 +21,7 @@ export type HttpError = { status: number; title: string; }; + +export type HttpValidationError = Omit & { + errors: Record; +}; diff --git a/apps/web/components/Form/Buttons.tsx b/apps/web/components/Form/Buttons.tsx index 31bc0e5..f454915 100644 --- a/apps/web/components/Form/Buttons.tsx +++ b/apps/web/components/Form/Buttons.tsx @@ -1,9 +1,21 @@ +'use client'; + +import { useFormStore } from '@/store/ius/form'; import { Button } from 'ui'; export function Buttons() { + const { reset } = useFormStore(); + return (
- +
diff --git a/apps/web/components/Form/Elements.tsx b/apps/web/components/Form/Elements.tsx index ba7d337..08b7a37 100644 --- a/apps/web/components/Form/Elements.tsx +++ b/apps/web/components/Form/Elements.tsx @@ -1,8 +1,18 @@ +'use client'; + import type { Props } from './types'; import { mapFieldTypeElement } from '@/config/elements'; +import { useFormStore } from '@/store/ius/form'; +import { useEffect } from 'react'; import { ElementContainer } from 'ui'; export function Elements({ data, metaData }: Props) { + const { init, setValue, values } = useFormStore(); + + useEffect(() => { + init(data); + }, [data, init]); + return (
{Object.keys(metaData).map((name) => { @@ -13,17 +23,16 @@ export function Elements({ data, metaData }: Props) { const Element = mapFieldTypeElement[fieldType]; return ( - + { + setValue({ name, value: e.target.value }); + }} {...props} /> diff --git a/apps/web/package.json b/apps/web/package.json index 144aa45..1c3254e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -15,7 +15,8 @@ "tsconfig": "*", "ui": "*", "wretch": "^2.7.0", - "zod": "^3.22.4" + "zod": "^3.22.4", + "zustand": "^4.4.6" }, "devDependencies": { "@tailwindcss/forms": "^0.5.6", diff --git a/apps/web/store/ius/form.ts b/apps/web/store/ius/form.ts new file mode 100644 index 0000000..1644588 --- /dev/null +++ b/apps/web/store/ius/form.ts @@ -0,0 +1,34 @@ +import type { ResponseGetData } from '@/api/ius/types'; +import { create } from 'zustand'; + +type Values = ResponseGetData; + +type FormState = { + defaultValues: Values; + init: (values: Values) => void; + reset: () => void; + setValue: ({ name, value }: { name: string; value: Values[number] }) => void; + values: Values; +}; + +export const useFormStore = create((set) => ({ + defaultValues: {}, + init: (values) => + set(() => ({ + defaultValues: values, + values, + })), + reset: () => { + set((state) => ({ + values: state.defaultValues, + })); + }, + setValue: ({ name, value }) => + set((state) => ({ + values: { + ...state.values, + [name]: value, + }, + })), + values: {}, +})); diff --git a/yarn.lock b/yarn.lock index 2bdf457..8820063 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5732,6 +5732,11 @@ urlpattern-polyfill@^8.0.0: resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -5967,3 +5972,10 @@ zod@^3.22.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + +zustand@^4.4.6: + version "4.4.6" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.6.tgz#03c78e3e2686c47095c93714c0c600b72a6512bd" + integrity sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg== + dependencies: + use-sync-external-store "1.2.0"