axp-ts/src/forms/fields.ts

203 lines
4.9 KiB
TypeScript
Raw Normal View History

2023-07-11 09:53:08 +03:00
import type { ZodTypeAny } from 'zod'
import type { TFormSchemaCtrlArgs } from './ctrl'
import { z } from 'zod'
import { GenderEnum } from '../entities'
import {
getPhoneNumberValue,
regexFIO,
validPhoneNumber,
regexSearch,
regexId
} from './helpers'
import { FormSchemaCtrl } from './ctrl'
2023-09-20 10:25:01 +03:00
export type TUiFieldSelectOption = {
text: string
value: string
}
2023-07-11 09:53:08 +03:00
/**
* Create field schema.
*/
export const fieldSchema = <T extends ZodTypeAny>(
base: T,
args?: TFormSchemaCtrlArgs
) => base.describe(FormSchemaCtrl.toString(args, base.description))
/**
* Base fields schema.
*/
export const bFieldsSchema = {
number: z
.preprocess(value => Number(value), z.number())
.describe(
FormSchemaCtrl.toString({
label: 'Номер',
type: 'number',
component: 'ui-field-number'
})
),
string: z
.string()
.trim()
.describe(
FormSchemaCtrl.toString({
label: 'Строка',
type: 'string',
component: 'ui-field-text'
})
),
date: z
.preprocess(value => new Date(String(value)), z.date())
.describe(
FormSchemaCtrl.toString({
label: 'Дата',
type: 'date',
component: 'ui-field-date'
})
),
boolean: z
.preprocess(value => String(value) === 'true', z.boolean())
.describe(
FormSchemaCtrl.toString({
label: 'Логическое значение',
type: 'boolean',
component: 'ui-field-checkbox'
})
)
}
/**
* Common fields schema.
*/
export const cFieldsSchema = z.object({
...bFieldsSchema,
_id: fieldSchema(bFieldsSchema.string.regex(regexId, 'Не валидный ID'), {
label: 'ID'
}),
dateCreate: fieldSchema(bFieldsSchema.date, {
label: 'Дата создания'
}),
dateUpdate: fieldSchema(bFieldsSchema.date, {
label: 'Дата изменения'
}),
name: fieldSchema(bFieldsSchema.string, {
label: 'Название'
}),
title: fieldSchema(bFieldsSchema.string, {
label: 'Заголовок'
}),
comment: fieldSchema(z.string().trim().min(2).max(1000), {
label: 'Комментарий',
component: 'ui-field-text-area'
}),
description: fieldSchema(z.string().trim().min(2).max(1000), {
label: 'Описание',
component: 'ui-field-text-area'
}),
text: fieldSchema(z.string().trim().min(2).max(3000), {
label: 'Текст',
component: 'ui-field-text-area'
}),
login: fieldSchema(bFieldsSchema.string, {
label: 'Логин'
}),
email: fieldSchema(bFieldsSchema.string.email(), {
label: 'Email'
}),
password: fieldSchema(bFieldsSchema.string.min(6), {
label: 'Пароль',
component: 'ui-field-password'
}),
price: fieldSchema(
z.preprocess(val => Number(val), z.number().nonnegative()),
{ label: 'Стоимость' }
),
alias: fieldSchema(
bFieldsSchema.string
.toLowerCase()
.regex(/^[a-z-]+$/, 'Только латиница и тире "-"'),
{ label: 'Псевдоним' }
),
published: fieldSchema(bFieldsSchema.boolean, {
label: 'Опубликован(а)'
}),
active: fieldSchema(bFieldsSchema.boolean, {
label: 'Активный(ная)'
}),
enabled: fieldSchema(bFieldsSchema.boolean, {
label: 'Включен(а)'
}),
disabled: fieldSchema(bFieldsSchema.boolean, {
label: 'Отключен(а)'
}),
open: fieldSchema(bFieldsSchema.boolean, {
label: 'Открыт(а)'
}),
close: fieldSchema(bFieldsSchema.boolean, {
label: 'Закрыто'
}),
closed: fieldSchema(bFieldsSchema.boolean, {
label: 'Закрыт(а)'
}),
online: fieldSchema(bFieldsSchema.boolean, {
label: 'Онлайн'
}),
firstName: fieldSchema(
bFieldsSchema.string.regex(regexFIO, 'Только кириллица'),
{ label: 'Имя' }
),
middleName: fieldSchema(
bFieldsSchema.string.regex(regexFIO, 'Только кириллица'),
{ label: 'Отчество' }
),
lastName: fieldSchema(
bFieldsSchema.string.regex(regexFIO, 'Только кириллица'),
{ label: 'Фамилия' }
),
birthday: fieldSchema(bFieldsSchema.date, {
label: 'Дата рождения'
}),
phone: fieldSchema(
z
.preprocess(val => getPhoneNumberValue(val) || 0, bFieldsSchema.number)
.refine(val => validPhoneNumber(val), {
message: 'Не вервый формат номера телефона'
}),
{
label: 'Телефон',
component: 'ui-field-phone'
}
),
gender: fieldSchema(z.enum([GenderEnum.man, GenderEnum.woman]), {
label: 'Пол',
component: 'ui-field-select-gender'
}),
year: fieldSchema(bFieldsSchema.number, {
label: 'Год'
}),
days: fieldSchema(bFieldsSchema.number.array(), {
label: 'Дни недели',
component: 'ui-picker-days'
2023-09-14 18:19:36 +03:00
}),
q: fieldSchema(
z.preprocess(
val => String(val).replace(regexSearch, ''),
bFieldsSchema.string
),
{
label: 'Поиск',
component: 'ui-field-search'
}
),
page: fieldSchema(
z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number),
{ label: 'Страница' }
),
limit: fieldSchema(
z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number),
{ label: 'Лимит' }
)
2023-07-11 09:53:08 +03:00
})