feat: temp barcode templates

This commit is contained in:
2024-05-07 08:07:18 +03:00
parent e157406787
commit 90802acc56
30 changed files with 723 additions and 26 deletions

View File

@@ -0,0 +1,14 @@
import {useQuery} from "@tanstack/react-query";
import {BarcodeService} from "../../client";
const useGetAllBarcodeTemplates = () => {
const {data, error, isLoading, refetch} = useQuery({
queryKey: ['getAllBarcodeTemplates'],
queryFn: () => BarcodeService.getAllBarcodeTemplates(),
select: (data) => data.templates
});
const barcodeTemplates = isLoading || error || !data ? [] : data;
return {barcodeTemplates, refetch}
}
export default useGetAllBarcodeTemplates;

View File

@@ -9,6 +9,12 @@ export type { OpenAPIConfig } from './core/OpenAPI';
export type { AuthLoginRequest } from './models/AuthLoginRequest'; export type { AuthLoginRequest } from './models/AuthLoginRequest';
export type { AuthLoginResponse } from './models/AuthLoginResponse'; export type { AuthLoginResponse } from './models/AuthLoginResponse';
export type { BarcodeTemplateAttributeSchema } from './models/BarcodeTemplateAttributeSchema';
export type { BarcodeTemplateCreateRequest } from './models/BarcodeTemplateCreateRequest';
export type { BarcodeTemplateCreateResponse } from './models/BarcodeTemplateCreateResponse';
export type { BarcodeTemplateSchema } from './models/BarcodeTemplateSchema';
export type { BarcodeTemplateUpdateRequest } from './models/BarcodeTemplateUpdateRequest';
export type { BarcodeTemplateUpdateResponse } from './models/BarcodeTemplateUpdateResponse';
export type { ClientCreateRequest } from './models/ClientCreateRequest'; export type { ClientCreateRequest } from './models/ClientCreateRequest';
export type { ClientCreateResponse } from './models/ClientCreateResponse'; export type { ClientCreateResponse } from './models/ClientCreateResponse';
export type { ClientDeleteRequest } from './models/ClientDeleteRequest'; export type { ClientDeleteRequest } from './models/ClientDeleteRequest';
@@ -19,6 +25,8 @@ export type { ClientSchema } from './models/ClientSchema';
export type { ClientUpdateDetailsRequest } from './models/ClientUpdateDetailsRequest'; export type { ClientUpdateDetailsRequest } from './models/ClientUpdateDetailsRequest';
export type { ClientUpdateRequest } from './models/ClientUpdateRequest'; export type { ClientUpdateRequest } from './models/ClientUpdateRequest';
export type { ClientUpdateResponse } from './models/ClientUpdateResponse'; export type { ClientUpdateResponse } from './models/ClientUpdateResponse';
export type { CreateBarcodeTemplateAttributeRequest } from './models/CreateBarcodeTemplateAttributeRequest';
export type { CreateBarcodeTemplateAttributeResponse } from './models/CreateBarcodeTemplateAttributeResponse';
export type { DealAddProductRequest } from './models/DealAddProductRequest'; export type { DealAddProductRequest } from './models/DealAddProductRequest';
export type { DealAddProductResponse } from './models/DealAddProductResponse'; export type { DealAddProductResponse } from './models/DealAddProductResponse';
export type { DealAddServiceRequest } from './models/DealAddServiceRequest'; export type { DealAddServiceRequest } from './models/DealAddServiceRequest';
@@ -55,6 +63,10 @@ export type { DealUpdateProductQuantityRequest } from './models/DealUpdateProduc
export type { DealUpdateProductQuantityResponse } from './models/DealUpdateProductQuantityResponse'; export type { DealUpdateProductQuantityResponse } from './models/DealUpdateProductQuantityResponse';
export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest'; export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest';
export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse'; export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse';
export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
export type { GetAllBarcodeTemplatesResponse } from './models/GetAllBarcodeTemplatesResponse';
export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest';
export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse';
export type { HTTPValidationError } from './models/HTTPValidationError'; export type { HTTPValidationError } from './models/HTTPValidationError';
export type { PaginationInfoSchema } from './models/PaginationInfoSchema'; export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
export type { ProductAddBarcodeRequest } from './models/ProductAddBarcodeRequest'; export type { ProductAddBarcodeRequest } from './models/ProductAddBarcodeRequest';
@@ -86,6 +98,7 @@ export type { UserSchema } from './models/UserSchema';
export type { ValidationError } from './models/ValidationError'; export type { ValidationError } from './models/ValidationError';
export { AuthService } from './services/AuthService'; export { AuthService } from './services/AuthService';
export { BarcodeService } from './services/BarcodeService';
export { ClientService } from './services/ClientService'; export { ClientService } from './services/ClientService';
export { DealService } from './services/DealService'; export { DealService } from './services/DealService';
export { ProductService } from './services/ProductService'; export { ProductService } from './services/ProductService';

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BarcodeTemplateAttributeSchema = {
id: number;
key: string;
name: string;
};

View File

@@ -0,0 +1,12 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BarcodeTemplateCreateRequest = {
name: string;
isDefault: boolean;
width: number;
height: number;
attributeIds: Array<number>;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BarcodeTemplateCreateResponse = {
ok: boolean;
message: string;
id: number;
};

View File

@@ -0,0 +1,14 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BarcodeTemplateAttributeSchema } from './BarcodeTemplateAttributeSchema';
export type BarcodeTemplateSchema = {
name: string;
isDefault: boolean;
width: number;
height: number;
id: number;
attributes: Array<BarcodeTemplateAttributeSchema>;
};

View File

@@ -0,0 +1,13 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BarcodeTemplateUpdateRequest = {
name: string;
isDefault: boolean;
width: number;
height: number;
id: number;
attributeIds: Array<number>;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BarcodeTemplateUpdateResponse = {
ok: boolean;
message: string;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type CreateBarcodeTemplateAttributeRequest = {
name: string;
label: string;
};

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type CreateBarcodeTemplateAttributeResponse = {
ok: boolean;
message: string;
id: number;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BarcodeTemplateAttributeSchema } from './BarcodeTemplateAttributeSchema';
export type GetAllBarcodeTemplateAttributesResponse = {
attributes: Array<BarcodeTemplateAttributeSchema>;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BarcodeTemplateSchema } from './BarcodeTemplateSchema';
export type GetAllBarcodeTemplatesResponse = {
templates: Array<BarcodeTemplateSchema>;
};

View File

@@ -0,0 +1,8 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type GetBarcodeTemplateByIdRequest = {
id: number;
};

View File

@@ -0,0 +1,9 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BarcodeTemplateSchema } from './BarcodeTemplateSchema';
export type GetBarcodeTemplateByIdResponse = {
barcodeTemplate: BarcodeTemplateSchema;
};

View File

@@ -0,0 +1,121 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { BarcodeTemplateCreateRequest } from '../models/BarcodeTemplateCreateRequest';
import type { BarcodeTemplateCreateResponse } from '../models/BarcodeTemplateCreateResponse';
import type { BarcodeTemplateUpdateRequest } from '../models/BarcodeTemplateUpdateRequest';
import type { BarcodeTemplateUpdateResponse } from '../models/BarcodeTemplateUpdateResponse';
import type { CreateBarcodeTemplateAttributeRequest } from '../models/CreateBarcodeTemplateAttributeRequest';
import type { CreateBarcodeTemplateAttributeResponse } from '../models/CreateBarcodeTemplateAttributeResponse';
import type { GetAllBarcodeTemplateAttributesResponse } from '../models/GetAllBarcodeTemplateAttributesResponse';
import type { GetAllBarcodeTemplatesResponse } from '../models/GetAllBarcodeTemplatesResponse';
import type { GetBarcodeTemplateByIdRequest } from '../models/GetBarcodeTemplateByIdRequest';
import type { GetBarcodeTemplateByIdResponse } from '../models/GetBarcodeTemplateByIdResponse';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class BarcodeService {
/**
* Get Barcode Template By Id
* @returns GetBarcodeTemplateByIdResponse Successful Response
* @throws ApiError
*/
public static getBarcodeTemplateById({
requestBody,
}: {
requestBody: GetBarcodeTemplateByIdRequest,
}): CancelablePromise<GetBarcodeTemplateByIdResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/barcode/template/get',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* Get All Barcode Templates
* @returns GetAllBarcodeTemplatesResponse Successful Response
* @throws ApiError
*/
public static getAllBarcodeTemplates(): CancelablePromise<GetAllBarcodeTemplatesResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/barcode/template/get-all',
});
}
/**
* Create Barcode Template
* @returns BarcodeTemplateCreateResponse Successful Response
* @throws ApiError
*/
public static createBarcodeTemplate({
requestBody,
}: {
requestBody: BarcodeTemplateCreateRequest,
}): CancelablePromise<BarcodeTemplateCreateResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/barcode/template/create',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* Update Barcode Template
* @returns BarcodeTemplateUpdateResponse Successful Response
* @throws ApiError
*/
public static updateBarcodeTemplate({
requestBody,
}: {
requestBody: BarcodeTemplateUpdateRequest,
}): CancelablePromise<BarcodeTemplateUpdateResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/barcode/template/update',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
/**
* Get All Barcode Template Attributes
* @returns GetAllBarcodeTemplateAttributesResponse Successful Response
* @throws ApiError
*/
public static getAllBarcodeTemplateAttributes(): CancelablePromise<GetAllBarcodeTemplateAttributesResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/barcode/template/attribute/get-all',
});
}
/**
* Create Barcode Template Attribute
* @returns CreateBarcodeTemplateAttributeResponse Successful Response
* @throws ApiError
*/
public static createBarcodeTemplateAttribute({
requestBody,
}: {
requestBody: CreateBarcodeTemplateAttributeRequest,
}): CancelablePromise<CreateBarcodeTemplateAttributeResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/barcode/template/attribute/create',
body: requestBody,
mediaType: 'application/json',
errors: {
422: `Validation Error`,
},
});
}
}

View File

@@ -0,0 +1,61 @@
import {MultiSelect, MultiSelectProps} from "@mantine/core";
import {useEffect, useMemo, useState} from "react";
import {ObjectWithNameAndId} from "../../types/utils.ts";
export type MultiselectObjectType<T extends ObjectWithNameAndId> = T;
type ControlledValueProps<T extends ObjectWithNameAndId> = {
value: MultiselectObjectType<T>[],
onChange: (value: MultiselectObjectType<T>[]) => void;
}
type RestProps<T extends ObjectWithNameAndId> = {
defaultValue?: MultiselectObjectType<T>[]
onChange: (value: MultiselectObjectType<T>[]) => void;
data: MultiselectObjectType<T>[];
}
export type ObjectMultiSelectProps<T extends ObjectWithNameAndId> =
(RestProps<T> & Partial<ControlledValueProps<T>>)
& Omit<MultiSelectProps, 'value' | 'onChange' | 'data'>;
const ObjectMultiSelect = <T extends ObjectWithNameAndId, >(props: ObjectMultiSelectProps<T>) => {
const isControlled = 'value' in props;
const [internalValue, setInternalValue] = useState<MultiselectObjectType<T>[] | undefined>(props.defaultValue);
const value = (isControlled ? props.value : internalValue) || [];
const data = useMemo(() => props.data.reduce((acc, item) => {
acc.push({
label: item.name,
value: item.id.toString()
});
return acc;
}, [] as { label: string, value: string }[]), [props.data]);
const handleOnChange = (event: string[]) => {
const objects = props.data.filter(item => event.includes(item.id.toString()));
if (isControlled) {
props.onChange(objects);
return;
}
setInternalValue(objects);
}
useEffect(() => {
if (isControlled || !internalValue) return;
props.onChange(internalValue);
}, [internalValue]);
return (
<MultiSelect
{...props}
value={value.map(item => item.id.toString())}
onChange={handleOnChange}
data={data}
/>
)
}
export default ObjectMultiSelect;

View File

@@ -0,0 +1,65 @@
import {Select, SelectProps} from "@mantine/core";
import {useEffect, useMemo, useState} from "react";
import {ObjectWithNameAndId} from "../../types/utils.ts";
export type SelectObjectType<T extends ObjectWithNameAndId> = T;
type ControlledValueProps<T extends ObjectWithNameAndId> = {
value: SelectObjectType<T>,
onChange: (value: SelectObjectType<T>) => void;
}
type RestProps<T extends ObjectWithNameAndId> = {
defaultValue?: SelectObjectType<T>
onChange: (value: SelectObjectType<T>) => void;
data: SelectObjectType<T>[];
}
export type ObjectSelectProps<T extends ObjectWithNameAndId> =
(RestProps<T> & Partial<ControlledValueProps<T>>)
& Omit<SelectProps, 'value' | 'onChange' | 'data'>;
const ObjectSelect = <T extends ObjectWithNameAndId, >(props: ObjectSelectProps<T>) => {
const isControlled = 'value' in props;
const [internalValue, setInternalValue] = useState<SelectObjectType<T> | undefined>(props.defaultValue);
const value = isControlled ? props.value : internalValue;
const data = useMemo(() => props.data.reduce((acc, item) => {
acc.push({
label: item.name,
value: item.id.toString()
});
return acc;
}, [] as { label: string, value: string }[]), [props.data]);
const handleOnChange = (event: string | null) => {
if (!event) return;
const object = props.data.find(item => parseInt(event) == item.id);
if (!object) return;
if (isControlled) {
props.onChange(object);
return;
}
setInternalValue(object);
}
useEffect(() => {
if (isControlled || !internalValue) return;
props.onChange(internalValue);
}, [internalValue]);
return (
<Select
{...props}
value={value?.id.toString()}
onChange={handleOnChange}
data={data}
/>
)
}
export default ObjectSelect;

View File

@@ -0,0 +1,18 @@
import ObjectSelect, {ObjectSelectProps} from "../../ObjectSelect/ObjectSelect.tsx";
import {BarcodeTemplateSchema} from "../../../client";
import useGetAllBarcodeTemplates from "../../../api/barcode/useGetAllBarcodeTemplates.tsx";
type Props = Omit<ObjectSelectProps<BarcodeTemplateSchema>, 'data'>;
const BarcodeTemplateSelect = (props: Props) => {
const {barcodeTemplates} = useGetAllBarcodeTemplates();
return (
<ObjectSelect
data={barcodeTemplates}
{...props}
/>
)
}
export default BarcodeTemplateSelect;

View File

@@ -7,6 +7,8 @@ import AddDealServiceModal from "../pages/LeadsPage/modals/AddDealServiceModal.t
import AddDealProductModal from "../pages/LeadsPage/modals/AddDealProductModal.tsx"; import AddDealProductModal from "../pages/LeadsPage/modals/AddDealProductModal.tsx";
import PrintBarcodeModal from "./PrintBarcodeModal/PrintBarcodeModal.tsx"; import PrintBarcodeModal from "./PrintBarcodeModal/PrintBarcodeModal.tsx";
import AddBarcodeModal from "./AddBarcodeModal/AddBarcodeModal.tsx"; import AddBarcodeModal from "./AddBarcodeModal/AddBarcodeModal.tsx";
import BarcodeTemplateFormModal
from "../pages/BarcodePage/modals/BarcodeTemplateFormModal/BarcodeTemplateFormModal.tsx";
export const modals = { export const modals = {
enterDeadline: EnterDeadlineModal, enterDeadline: EnterDeadlineModal,
@@ -17,5 +19,6 @@ export const modals = {
addDealService: AddDealServiceModal, addDealService: AddDealServiceModal,
addDealProduct: AddDealProductModal, addDealProduct: AddDealProductModal,
printBarcode: PrintBarcodeModal, printBarcode: PrintBarcodeModal,
addBarcode: AddBarcodeModal addBarcode: AddBarcodeModal,
barcodeTemplateFormModal: BarcodeTemplateFormModal
} }

View File

@@ -0,0 +1,12 @@
.container {
display: flex;
flex-direction: column;
flex: 1;
gap: rem(10);
}
.top-panel {
padding: rem(5);
gap: rem(10);
display: flex;
}

View File

@@ -0,0 +1,27 @@
import styles from './BarcodePage.module.css';
import PageBlock from "../../components/PageBlock/PageBlock.tsx";
import {Button} from "@mantine/core";
const BarcodePage = () => {
return (
<div className={styles['container']}>
<PageBlock>
<div className={styles['top-panel']}>
<Button
variant={"default"}
>
Создать клиента
</Button>
</div>
</PageBlock>
<PageBlock>
<>dsad</>
</PageBlock>
</div>
)
}
export default BarcodePage;

View File

@@ -0,0 +1,20 @@
import ObjectMultiSelect, {
ObjectMultiSelectProps
} from "../../../../components/ObjectMultiSelect/ObjectMultiSelect.tsx";
import {BarcodeTemplateAttributeSchema} from "../../../../client";
import {FC} from "react";
import useBarcodeTemplateAttributesList from "../../hooks/useBarcodeTemplateAttributesList.tsx";
type Props = Omit<ObjectMultiSelectProps<BarcodeTemplateAttributeSchema>, 'data'>
const BarcodeTemplateAttributeMultiselect: FC<Props> = (props: Props) => {
const {barcodeTemplateAttributes} = useBarcodeTemplateAttributesList();
return (
<ObjectMultiSelect
data={barcodeTemplateAttributes}
{...props}
/>
)
}
export default BarcodeTemplateAttributeMultiselect;

View File

@@ -0,0 +1,62 @@
import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
import {BarcodeTemplateSchema} from "../../../../client";
import {FC} from "react";
import {useBarcodeTemplatesTableColumns} from "./columns.tsx";
import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx";
import {modals} from "@mantine/modals";
import {ActionIcon, Flex, Tooltip} from "@mantine/core";
import {IconEdit, IconTrash} from "@tabler/icons-react";
const BarcodeTemplatesTable: FC<CRUDTableProps<BarcodeTemplateSchema>> = ({
items,
onDelete,
onChange
}) => {
const columns = useBarcodeTemplatesTableColumns();
const onEditClick = (template: BarcodeTemplateSchema) => {
if (!onChange) return;
modals.openContextModal({
modal: "barcodeTemplateFormModal",
title: 'Создание шаблона',
withCloseButton: false,
innerProps: {
onChange: (newTemplate) => onChange(newTemplate),
element: template,
}
});
}
return (
<>
<BaseTable
striped
data={items}
columns={columns}
restProps={{
enableColumnActions: false,
enableRowActions: true,
renderRowActions: ({row}) => (
<Flex gap="md">
<Tooltip label="Редактировать">
<ActionIcon
onClick={() => onEditClick(row.original)}
variant={"default"}
>
<IconEdit/>
</ActionIcon>
</Tooltip>
<Tooltip label="Удалить">
<ActionIcon onClick={() => {
if (onDelete) onDelete(row.original);
}} variant={"default"}>
<IconTrash/>
</ActionIcon>
</Tooltip>
</Flex>
)
}}
/>
</>
)
}
export default BarcodeTemplatesTable;

View File

@@ -0,0 +1,24 @@
import {BarcodeTemplateSchema} from "../../../../client";
import {MRT_ColumnDef} from "mantine-react-table";
import {useMemo} from "react";
export const useBarcodeTemplatesTableColumns = () => {
return useMemo<MRT_ColumnDef<BarcodeTemplateSchema>[]>(() => [
{
accessorKey: "name",
header: "Название",
},
{
accessorKey: "isDefault",
header: "По умолчанию",
},
{
accessorKey: "attributes",
header: "Атрибуты",
},
{
header: "Размер",
Cell: ({row}) => <>{row.original.width}x{row.original.height}</>
}
], []);
}

View File

@@ -0,0 +1,14 @@
import {BarcodeService} from "../../../client";
import {useQuery} from "@tanstack/react-query";
const useBarcodeTemplateAttributesList = () => {
const {isLoading, data, error, refetch} = useQuery({
queryKey: ['getAllBarcodeTemplateAttributes'],
queryFn: BarcodeService.getAllBarcodeTemplateAttributes
});
const barcodeTemplateAttributes = isLoading || error || !data ? [] : data.attributes;
return {barcodeTemplateAttributes, refetch}
}
export default useBarcodeTemplateAttributesList;

View File

@@ -0,0 +1,91 @@
import BaseFormModal, {CreateEditFormProps} from "../../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
import {BarcodeTemplateAttributeSchema, BarcodeTemplateSchema} from "../../../../client";
import {ContextModalProps} from "@mantine/modals";
import {useForm} from "@mantine/form";
import {Checkbox, Fieldset, Flex, NumberInput, rem, TextInput} from "@mantine/core";
import {IconX} from "@tabler/icons-react";
import BarcodeTemplateAttributeMultiselect
from "../../component/BarcodeTemplateAttributeMultiselect/BarcodeTemplateAttributeMultiselect.tsx";
type Props = CreateEditFormProps<BarcodeTemplateSchema>
const BarcodeTemplateFormModal = ({
context,
id,
innerProps
}: ContextModalProps<Props>) => {
const isEditing = 'onChange' in innerProps;
const initialValues = isEditing ? innerProps.element : {
name: "",
width: undefined,
height: undefined,
isDefault: false,
attributes: [] as Array<BarcodeTemplateAttributeSchema>
} as Partial<BarcodeTemplateSchema>;
const form = useForm<Partial<BarcodeTemplateSchema>>({
initialValues: initialValues,
validate: {
width: (width: number | undefined) => width && width > 0 ? null : "Ширина должна быть больше 0",
height: (height: number | undefined) => height && height > 0 ? null : "Высота должна быть больше 0",
attributes: (attributes: Array<BarcodeTemplateAttributeSchema> | undefined) => attributes && attributes.length > 0 ? null : "Необходимо добавить хотя бы один атрибут",
name: (name: string | undefined) => name && name.trim() !== '' ? null : "Необходимо ввести название шаблона",
}
})
console.log(form.values);
return (
<BaseFormModal
{...innerProps}
closeOnSubmit
form={form}
onClose={() => context.closeContextModal(id)}
>
<BaseFormModal.Body>
<>
<Fieldset legend={"Шаблон штрихкода"}>
<Flex direction={"column"} gap={rem(10)}>
<TextInput
label={"Название"}
placeholder={"Введите название шаблона"}
{...form.getInputProps('name')}
/>
<Fieldset
styles={{
legend: {
marginBottom: 0,
fontWeight: 500
}
}}
variant={"unstyled"}
legend={"Размер"}>
<Flex gap={10} align={"center"}>
<NumberInput
hideControls
placeholder={"Ширина"}
{...form.getInputProps('width')}
/>
<IconX/>
<NumberInput
hideControls
placeholder={"Высота"}
{...form.getInputProps('height')}
/>
</Flex>
</Fieldset>
<BarcodeTemplateAttributeMultiselect
label={"Атрибуты"}
placeholder={"Выберите атрибуты"}
{...form.getInputProps('attributes')}
/>
<Checkbox
label={"Использовать как стандартный шаблон"}
{...form.getInputProps('isDefault')}/>
</Flex>
</Fieldset>
</>
</BaseFormModal.Body>
</BaseFormModal>
)
}
export default BarcodeTemplateFormModal;

View File

@@ -22,6 +22,7 @@ const ProductsLazyImport = createFileRoute('/products')()
const LoginLazyImport = createFileRoute('/login')() const LoginLazyImport = createFileRoute('/login')()
const LeadsLazyImport = createFileRoute('/leads')() const LeadsLazyImport = createFileRoute('/leads')()
const ClientsLazyImport = createFileRoute('/clients')() const ClientsLazyImport = createFileRoute('/clients')()
const BarcodeLazyImport = createFileRoute('/barcode')()
const IndexLazyImport = createFileRoute('/')() const IndexLazyImport = createFileRoute('/')()
// Create/Update Routes // Create/Update Routes
@@ -56,6 +57,11 @@ const ClientsLazyRoute = ClientsLazyImport.update({
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/clients.lazy').then((d) => d.Route)) } as any).lazy(() => import('./routes/clients.lazy').then((d) => d.Route))
const BarcodeLazyRoute = BarcodeLazyImport.update({
path: '/barcode',
getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/barcode.lazy').then((d) => d.Route))
const IndexLazyRoute = IndexLazyImport.update({ const IndexLazyRoute = IndexLazyImport.update({
path: '/', path: '/',
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
@@ -69,6 +75,10 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexLazyImport preLoaderRoute: typeof IndexLazyImport
parentRoute: typeof rootRoute parentRoute: typeof rootRoute
} }
'/barcode': {
preLoaderRoute: typeof BarcodeLazyImport
parentRoute: typeof rootRoute
}
'/clients': { '/clients': {
preLoaderRoute: typeof ClientsLazyImport preLoaderRoute: typeof ClientsLazyImport
parentRoute: typeof rootRoute parentRoute: typeof rootRoute
@@ -100,6 +110,7 @@ declare module '@tanstack/react-router' {
export const routeTree = rootRoute.addChildren([ export const routeTree = rootRoute.addChildren([
IndexLazyRoute, IndexLazyRoute,
BarcodeLazyRoute,
ClientsLazyRoute, ClientsLazyRoute,
LeadsLazyRoute, LeadsLazyRoute,
LoginLazyRoute, LoginLazyRoute,

View File

@@ -0,0 +1,6 @@
import {createLazyFileRoute} from "@tanstack/react-router";
import BarcodePage from "../pages/BarcodePage/BarcodePage.tsx";
export const Route = createLazyFileRoute('/barcode')({
component: BarcodePage
})

View File

@@ -1,35 +1,44 @@
import {createLazyFileRoute} from "@tanstack/react-router"; import {createLazyFileRoute} from "@tanstack/react-router";
import {Button, Text} from "@mantine/core"; import {Fieldset, Flex, NumberInput} from "@mantine/core";
import {modals} from "@mantine/modals"; import {IconCross, IconX} from "@tabler/icons-react";
import {useEffect} from "react";
import {openContextModal} from "@mantine/modals";
export const Route = createLazyFileRoute('/test')({ export const Route = createLazyFileRoute('/test')({
component: TestPage component: TestPage
}) })
function TestPage() { function TestPage() {
return (
<Button useEffect(() => {
onClick={() => openContextModal({
modals.openConfirmModal({ modal: "barcodeTemplateFormModal",
title: 'Please confirm your action', withCloseButton: false,
closeOnConfirm: false, innerProps: {
labels: {confirm: 'Next modal', cancel: 'Close modal'}, onCreate: () => {
onConfirm: () => }
modals.openConfirmModal({
title: 'This is modal at second layer',
labels: {confirm: 'Close modal', cancel: 'Back'},
closeOnConfirm: false,
children: (
<Text size="sm">
When this modal is closed modals state will revert to first modal
</Text>
),
onConfirm: modals.closeAll,
}),
})
} }
> })
Open multiple steps modal }, []);
</Button> return (
<>
<Fieldset legend={"Размеры"}>
<Flex gap={10} align={"center"}>
<NumberInput
hideControls
placeholder={"Ширина"}
/>
<IconX/>
<NumberInput
hideControls
placeholder={"Высота"}
/>
</Flex>
</Fieldset>
</>
); );
} }

4
src/types/utils.ts Normal file
View File

@@ -0,0 +1,4 @@
export type ObjectWithNameAndId = {
id: number;
name: string;
}