apps/web: add base elements validation

This commit is contained in:
vchikalkin 2023-11-16 17:09:22 +03:00
parent 5d8aecfeb0
commit 0d8ea70734
11 changed files with 76 additions and 38 deletions

View File

@ -1,9 +1,10 @@
import type * as t from './types';
import { urls } from '@/config/urls';
import { getUrls } from '@/config/urls';
import type { CreateUrl } from '@/utils/url';
import type { WretchError } from 'wretch';
import wretch from 'wretch';
const urls = getUrls();
const api = wretch(urls.URL_UIS).errorType('json');
type Input = { createUrl: CreateUrl; payload?: unknown };
@ -44,11 +45,11 @@ export async function getConditions({ createUrl }: Input) {
.then((res) => res);
}
export async function validate({ createUrl }: Input) {
export async function validate({ createUrl, payload }: Input) {
const url = createUrl('/validate');
return api
.post(url)
.post(payload, url)
.res<boolean>((res) => res.ok)
.then((res) => res)
.catch((error: WretchError) => error.json as t.HttpValidationError);

View File

@ -33,14 +33,14 @@ export default async function Page(pageProps: PageProps) {
apiIUS.getMetaData({ createUrl }),
apiIUS.getConfig({ createUrl }),
]).then(([data, metaData, { title }]) => {
const props = { data, metaData };
const props = { data, metaData, pageUrlParams };
return (
<Background>
<Form.Header {...props} url={'/ius' + createUrl('/conditions')} title={title} />
<Form.Elements {...props} />
<Divider />
<Form.Buttons />
<Form.Buttons {...props} />
</Background>
);
});

View File

@ -1,10 +1,12 @@
'use client';
import * as apiIus from '@/api/ius/query';
import { useFormStore } from '@/store/ius/form';
import { makeCreateUrl, type PageUrlParams } from '@/utils/url';
import { Button } from 'ui';
export function Buttons() {
const { reset } = useFormStore();
export function Buttons({ pageUrlParams }: { readonly pageUrlParams: PageUrlParams }) {
const { reset, setValidation, values } = useFormStore();
const createUrl = makeCreateUrl(pageUrlParams);
return (
<div className="grid grid-cols-1 gap-2 gap-x-4 md:grid-cols-3">
@ -17,7 +19,21 @@ export function Buttons() {
Отмена
</Button>
<Button intent="secondary">Возврат на доработку</Button>
<Button>Сохранить</Button>
<Button
onClick={() => {
apiIus.validate({ createUrl, payload: values }).then((res) => {
if (typeof res !== 'boolean') {
Object.keys(res.errors).forEach((name) => {
const elementValidation = res?.errors?.[name];
if (elementValidation)
setValidation({ message: elementValidation[0] ?? '', name, valid: false });
});
}
});
}}
>
Сохранить
</Button>
</div>
);
}

View File

@ -7,7 +7,7 @@ import { useEffect } from 'react';
import { ElementContainer } from 'ui';
export function Elements({ data, metaData }: Props) {
const { init, setValue, values } = useFormStore();
const { init, setValue, validation, values } = useFormStore();
useEffect(() => {
init(data);
@ -23,7 +23,13 @@ export function Elements({ data, metaData }: Props) {
const Element = mapFieldTypeElement[fieldType];
return (
<ElementContainer key={name} id={name} title={fieldType === 'CHECKBOX' ? '' : label}>
<ElementContainer
intent={validation[name] ? 'danger' : 'default'}
message={validation[name]?.message}
key={name}
id={name}
title={fieldType === 'CHECKBOX' ? '' : label}
>
<Element
loading={!Object.keys(values).length}
checked={fieldType === 'CHECKBOX' ? Boolean(values[name]) || false : false}

View File

@ -1,17 +1,5 @@
const envSchema = require('./schema/env.js');
const env = envSchema.parse(process.env);
const getEnv = () => envSchema.parse(process.env);
const serverEnv = envSchema
.pick({
URL_IUS_DIRECT: true,
})
.parse(process.env);
const clientEnv = envSchema
.pick({
USE_DEV_COLORS: true,
})
.parse(process.env);
module.exports = { clientEnv, env, serverEnv };
module.exports = { getEnv };

View File

@ -1,11 +1,18 @@
import { serverEnv } from './env';
import { getEnv } from './env';
import proxyUrls from '@/constants/urls';
import { isServer } from '@/utils/common';
export const urls = isServer
? {
URL_UIS: serverEnv.URL_IUS_DIRECT,
}
: {
URL_UIS: proxyUrls.URL_IUS_PROXY,
export function getUrls() {
if (isServer()) {
const env = getEnv();
const { URL_IUS_DIRECT } = env;
return {
URL_UIS: URL_IUS_DIRECT,
};
}
return {
URL_UIS: proxyUrls.URL_IUS_PROXY,
};
}

View File

@ -1,4 +1,4 @@
import { env } from '../config/env';
import { getEnv } from '../config/env';
export const COLORS_PROD = {
COLOR_DANGER: '#B20004',
@ -12,5 +12,5 @@ export const COLORS_DEV = {
COLOR_SECONDARY: '#FD4047',
COLOR_TERTIARTY: '#FF9112',
};
const env = getEnv();
export const COLORS = env.USE_DEV_COLORS ? COLORS_DEV : COLORS_PROD;

View File

@ -20,8 +20,8 @@ const nextConfig = {
async rewrites() {
return [
{
destination: env.URL_IUS_DIRECT + '/:path',
source: urls.URL_IUS_PROXY + '/:path',
destination: env.URL_IUS_DIRECT + '/:path*',
source: urls.URL_IUS_PROXY + '/:path*',
},
...favicons.map((fileName) => buildFaviconRewrite(`/${fileName}`)),
];

View File

@ -3,11 +3,18 @@ import { create } from 'zustand';
type Values = ResponseGetData;
type ElementValidation = {
message: string;
valid: boolean;
};
type FormState = {
defaultValues: Values;
init: (values: Values) => void;
reset: () => void;
setValidation: (input: { name: string } & ElementValidation) => void;
setValue: ({ name, value }: { name: string; value: Values[number] }) => void;
validation: Record<string, ElementValidation | undefined>;
values: Values;
};
@ -23,12 +30,25 @@ export const useFormStore = create<FormState>((set) => ({
values: state.defaultValues,
}));
},
setValidation: ({ message, name, valid }) => {
set((state) => ({
validation: {
...state.validation,
[name]: { message, valid },
},
}));
},
setValue: ({ name, value }) =>
set((state) => ({
validation: {
...state.validation,
[name]: undefined,
},
values: {
...state.values,
[name]: value,
},
})),
validation: {},
values: {},
}));

View File

@ -1 +1 @@
export const isServer = typeof window === 'undefined';
export const isServer = () => typeof window === 'undefined';

View File

@ -8,7 +8,7 @@ export type PageUrlParams = ReturnType<typeof getPageUrlParams>;
export function makeCreateUrl({ path, urlSearchParams }: ReturnType<typeof getPageUrlParams>) {
return function (route: string) {
if (urlSearchParams) return `${path}${route}?${urlSearchParams}`;
if (urlSearchParams) return `${path}${route}?${new URLSearchParams(urlSearchParams)}`;
return path + route;
};