apps/web: add base elements validation
This commit is contained in:
parent
5d8aecfeb0
commit
0d8ea70734
@ -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);
|
||||
|
||||
@ -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>
|
||||
);
|
||||
});
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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}`)),
|
||||
];
|
||||
|
||||
@ -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: {},
|
||||
}));
|
||||
|
||||
@ -1 +1 @@
|
||||
export const isServer = typeof window === 'undefined';
|
||||
export const isServer = () => typeof window === 'undefined';
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user