crap
This commit is contained in:
		@@ -30,16 +30,20 @@
 | 
			
		||||
    "clsx": "^2.1.0",
 | 
			
		||||
    "dayjs": "^1.11.10",
 | 
			
		||||
    "dot-object": "^2.1.4",
 | 
			
		||||
    "lodash": "^4.17.21",
 | 
			
		||||
    "mantine-form-zod-resolver": "^1.1.0",
 | 
			
		||||
    "mantine-react-table": "^2.0.0-beta.0",
 | 
			
		||||
    "react": "^18.2.0",
 | 
			
		||||
    "react-barcode": "^1.5.1",
 | 
			
		||||
    "react-dom": "^18.2.0",
 | 
			
		||||
    "react-redux": "^9.1.0",
 | 
			
		||||
    "react-to-print": "^2.15.1",
 | 
			
		||||
    "reactflow": "^11.10.4",
 | 
			
		||||
    "zod": "^3.22.4"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/dot-object": "^2",
 | 
			
		||||
    "@types/lodash": "^4",
 | 
			
		||||
    "@types/react": "^18.2.56",
 | 
			
		||||
    "@types/react-dom": "^18.2.19",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^7.0.2",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								src/api/product/useGetProductById.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/api/product/useGetProductById.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import {ProductService} from "../../client";
 | 
			
		||||
import {useQuery} from "@tanstack/react-query";
 | 
			
		||||
 | 
			
		||||
export const useGetProductById = (id: number) => {
 | 
			
		||||
    const {data, error, isLoading, refetch} = useQuery({
 | 
			
		||||
        queryKey: ['getProductById', id],
 | 
			
		||||
        queryFn: () => ProductService.getProductById({productId: id}),
 | 
			
		||||
        select: (data) => data
 | 
			
		||||
    });
 | 
			
		||||
    return {product: data, error, isLoading, refetch}
 | 
			
		||||
}
 | 
			
		||||
@@ -19,6 +19,8 @@ export type { ClientSchema } from './models/ClientSchema';
 | 
			
		||||
export type { ClientUpdateDetailsRequest } from './models/ClientUpdateDetailsRequest';
 | 
			
		||||
export type { ClientUpdateRequest } from './models/ClientUpdateRequest';
 | 
			
		||||
export type { ClientUpdateResponse } from './models/ClientUpdateResponse';
 | 
			
		||||
export type { DealAddProductRequest } from './models/DealAddProductRequest';
 | 
			
		||||
export type { DealAddProductResponse } from './models/DealAddProductResponse';
 | 
			
		||||
export type { DealAddServiceRequest } from './models/DealAddServiceRequest';
 | 
			
		||||
export type { DealAddServiceResponse } from './models/DealAddServiceResponse';
 | 
			
		||||
export type { DealAddServicesRequest } from './models/DealAddServicesRequest';
 | 
			
		||||
@@ -26,26 +28,41 @@ export type { DealAddServicesResponse } from './models/DealAddServicesResponse';
 | 
			
		||||
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
 | 
			
		||||
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
 | 
			
		||||
export type { DealCreateRequest } from './models/DealCreateRequest';
 | 
			
		||||
export type { DealDeleteProductRequest } from './models/DealDeleteProductRequest';
 | 
			
		||||
export type { DealDeleteProductResponse } from './models/DealDeleteProductResponse';
 | 
			
		||||
export type { DealDeleteProductsRequest } from './models/DealDeleteProductsRequest';
 | 
			
		||||
export type { DealDeleteProductsResponse } from './models/DealDeleteProductsResponse';
 | 
			
		||||
export type { DealDeleteServiceRequest } from './models/DealDeleteServiceRequest';
 | 
			
		||||
export type { DealDeleteServiceResponse } from './models/DealDeleteServiceResponse';
 | 
			
		||||
export type { DealDeleteServicesRequest } from './models/DealDeleteServicesRequest';
 | 
			
		||||
export type { DealDeleteServicesResponse } from './models/DealDeleteServicesResponse';
 | 
			
		||||
export type { DealGeneralInfoSchema } from './models/DealGeneralInfoSchema';
 | 
			
		||||
export type { DealGetAllResponse } from './models/DealGetAllResponse';
 | 
			
		||||
export type { DealProductSchema } from './models/DealProductSchema';
 | 
			
		||||
export type { DealQuickCreateRequest } from './models/DealQuickCreateRequest';
 | 
			
		||||
export type { DealQuickCreateResponse } from './models/DealQuickCreateResponse';
 | 
			
		||||
export type { DealSchema } from './models/DealSchema';
 | 
			
		||||
export type { DealServiceSchema } from './models/DealServiceSchema';
 | 
			
		||||
export type { DealStatusHistorySchema } from './models/DealStatusHistorySchema';
 | 
			
		||||
export type { DealSummary } from './models/DealSummary';
 | 
			
		||||
export type { DealSummaryResponse } from './models/DealSummaryResponse';
 | 
			
		||||
export type { DealUpdateGeneralInfoRequest } from './models/DealUpdateGeneralInfoRequest';
 | 
			
		||||
export type { DealUpdateGeneralInfoResponse } from './models/DealUpdateGeneralInfoResponse';
 | 
			
		||||
export type { DealUpdateProductQuantityRequest } from './models/DealUpdateProductQuantityRequest';
 | 
			
		||||
export type { DealUpdateProductQuantityResponse } from './models/DealUpdateProductQuantityResponse';
 | 
			
		||||
export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest';
 | 
			
		||||
export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse';
 | 
			
		||||
export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
			
		||||
export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
 | 
			
		||||
export type { ProductAddBarcodeRequest } from './models/ProductAddBarcodeRequest';
 | 
			
		||||
export type { ProductAddBarcodeResponse } from './models/ProductAddBarcodeResponse';
 | 
			
		||||
export type { ProductCreateRequest } from './models/ProductCreateRequest';
 | 
			
		||||
export type { ProductCreateResponse } from './models/ProductCreateResponse';
 | 
			
		||||
export type { ProductDeleteRequest } from './models/ProductDeleteRequest';
 | 
			
		||||
export type { ProductDeleteResponse } from './models/ProductDeleteResponse';
 | 
			
		||||
export type { ProductExistsBarcodeResponse } from './models/ProductExistsBarcodeResponse';
 | 
			
		||||
export type { ProductGenerateBarcodeRequest } from './models/ProductGenerateBarcodeRequest';
 | 
			
		||||
export type { ProductGenerateBarcodeResponse } from './models/ProductGenerateBarcodeResponse';
 | 
			
		||||
export type { ProductGetResponse } from './models/ProductGetResponse';
 | 
			
		||||
export type { ProductSchema } from './models/ProductSchema';
 | 
			
		||||
export type { ProductUpdateRequest } from './models/ProductUpdateRequest';
 | 
			
		||||
@@ -58,6 +75,7 @@ export type { ServiceCreateResponse } from './models/ServiceCreateResponse';
 | 
			
		||||
export type { ServiceGetAllCategoriesResponse } from './models/ServiceGetAllCategoriesResponse';
 | 
			
		||||
export type { ServiceGetAllResponse } from './models/ServiceGetAllResponse';
 | 
			
		||||
export type { ServiceSchema } from './models/ServiceSchema';
 | 
			
		||||
export type { UserSchema } from './models/UserSchema';
 | 
			
		||||
export type { ValidationError } from './models/ValidationError';
 | 
			
		||||
 | 
			
		||||
export { AuthService } from './services/AuthService';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/client/models/DealAddProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealAddProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealAddProductRequest = {
 | 
			
		||||
    dealId: number;
 | 
			
		||||
    productId: number;
 | 
			
		||||
    quantity: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealAddProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealAddProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealAddProductResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealDeleteProductRequest = {
 | 
			
		||||
    dealId: number;
 | 
			
		||||
    productId: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealDeleteProductResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteProductsRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteProductsRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealDeleteProductsRequest = {
 | 
			
		||||
    dealId: number;
 | 
			
		||||
    productIds: Array<number>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteProductsResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteProductsResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealDeleteProductsResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/client/models/DealGeneralInfoSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealGeneralInfoSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealGeneralInfoSchema = {
 | 
			
		||||
    name: string;
 | 
			
		||||
    isDeleted: boolean;
 | 
			
		||||
    isCompleted: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2,8 +2,10 @@
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
import type { ClientSchema } from './ClientSchema';
 | 
			
		||||
import type { DealProductSchema } from './DealProductSchema';
 | 
			
		||||
import type { DealServiceSchema } from './DealServiceSchema';
 | 
			
		||||
import type { DealStatusHistorySchema } from './DealStatusHistorySchema';
 | 
			
		||||
export type DealSchema = {
 | 
			
		||||
    id: number;
 | 
			
		||||
    name: string;
 | 
			
		||||
@@ -12,5 +14,9 @@ export type DealSchema = {
 | 
			
		||||
    currentStatus: number;
 | 
			
		||||
    services: Array<DealServiceSchema>;
 | 
			
		||||
    products: Array<DealProductSchema>;
 | 
			
		||||
    statusHistory: Array<DealStatusHistorySchema>;
 | 
			
		||||
    isDeleted: boolean;
 | 
			
		||||
    isCompleted: boolean;
 | 
			
		||||
    client: ClientSchema;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								src/client/models/DealStatusHistorySchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/client/models/DealStatusHistorySchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
import type { UserSchema } from './UserSchema';
 | 
			
		||||
export type DealStatusHistorySchema = {
 | 
			
		||||
    user: UserSchema;
 | 
			
		||||
    changedAt: string;
 | 
			
		||||
    fromStatus: number;
 | 
			
		||||
    toStatus: number;
 | 
			
		||||
    nextStatusDeadline: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/client/models/DealUpdateGeneralInfoRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealUpdateGeneralInfoRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
import type { DealGeneralInfoSchema } from './DealGeneralInfoSchema';
 | 
			
		||||
export type DealUpdateGeneralInfoRequest = {
 | 
			
		||||
    dealId: number;
 | 
			
		||||
    data: DealGeneralInfoSchema;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealUpdateGeneralInfoResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealUpdateGeneralInfoResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealUpdateGeneralInfoResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/client/models/DealUpdateProductQuantityRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealUpdateProductQuantityRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealUpdateProductQuantityRequest = {
 | 
			
		||||
    dealId: number;
 | 
			
		||||
    productId: number;
 | 
			
		||||
    quantity: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/DealUpdateProductQuantityResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealUpdateProductQuantityResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type DealUpdateProductQuantityResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/ProductAddBarcodeRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/ProductAddBarcodeRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type ProductAddBarcodeRequest = {
 | 
			
		||||
    productId: number;
 | 
			
		||||
    barcode: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/client/models/ProductAddBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/ProductAddBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type ProductAddBarcodeResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								src/client/models/ProductExistsBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/client/models/ProductExistsBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type ProductExistsBarcodeResponse = {
 | 
			
		||||
    exists: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								src/client/models/ProductGenerateBarcodeRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/client/models/ProductGenerateBarcodeRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type ProductGenerateBarcodeRequest = {
 | 
			
		||||
    productId: number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/client/models/ProductGenerateBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/ProductGenerateBarcodeResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type ProductGenerateBarcodeResponse = {
 | 
			
		||||
    ok: boolean;
 | 
			
		||||
    message: string;
 | 
			
		||||
    barcode: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								src/client/models/UserSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/client/models/UserSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
/* generated using openapi-typescript-codegen -- do no edit */
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export type UserSchema = {
 | 
			
		||||
    id: number;
 | 
			
		||||
    telegramId: number;
 | 
			
		||||
    phoneNumber?: (string | null);
 | 
			
		||||
    isAdmin: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -2,6 +2,8 @@
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
import type { DealAddProductRequest } from '../models/DealAddProductRequest';
 | 
			
		||||
import type { DealAddProductResponse } from '../models/DealAddProductResponse';
 | 
			
		||||
import type { DealAddServiceRequest } from '../models/DealAddServiceRequest';
 | 
			
		||||
import type { DealAddServiceResponse } from '../models/DealAddServiceResponse';
 | 
			
		||||
import type { DealAddServicesRequest } from '../models/DealAddServicesRequest';
 | 
			
		||||
@@ -9,6 +11,10 @@ import type { DealAddServicesResponse } from '../models/DealAddServicesResponse'
 | 
			
		||||
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
 | 
			
		||||
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
 | 
			
		||||
import type { DealCreateRequest } from '../models/DealCreateRequest';
 | 
			
		||||
import type { DealDeleteProductRequest } from '../models/DealDeleteProductRequest';
 | 
			
		||||
import type { DealDeleteProductResponse } from '../models/DealDeleteProductResponse';
 | 
			
		||||
import type { DealDeleteProductsRequest } from '../models/DealDeleteProductsRequest';
 | 
			
		||||
import type { DealDeleteProductsResponse } from '../models/DealDeleteProductsResponse';
 | 
			
		||||
import type { DealDeleteServiceRequest } from '../models/DealDeleteServiceRequest';
 | 
			
		||||
import type { DealDeleteServiceResponse } from '../models/DealDeleteServiceResponse';
 | 
			
		||||
import type { DealDeleteServicesRequest } from '../models/DealDeleteServicesRequest';
 | 
			
		||||
@@ -18,6 +24,10 @@ import type { DealQuickCreateRequest } from '../models/DealQuickCreateRequest';
 | 
			
		||||
import type { DealQuickCreateResponse } from '../models/DealQuickCreateResponse';
 | 
			
		||||
import type { DealSchema } from '../models/DealSchema';
 | 
			
		||||
import type { DealSummaryResponse } from '../models/DealSummaryResponse';
 | 
			
		||||
import type { DealUpdateGeneralInfoRequest } from '../models/DealUpdateGeneralInfoRequest';
 | 
			
		||||
import type { DealUpdateGeneralInfoResponse } from '../models/DealUpdateGeneralInfoResponse';
 | 
			
		||||
import type { DealUpdateProductQuantityRequest } from '../models/DealUpdateProductQuantityRequest';
 | 
			
		||||
import type { DealUpdateProductQuantityResponse } from '../models/DealUpdateProductQuantityResponse';
 | 
			
		||||
import type { DealUpdateServiceQuantityRequest } from '../models/DealUpdateServiceQuantityRequest';
 | 
			
		||||
import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
			
		||||
import type { CancelablePromise } from '../core/CancelablePromise';
 | 
			
		||||
@@ -95,6 +105,58 @@ export class DealService {
 | 
			
		||||
            url: '/deal/summaries',
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Get All
 | 
			
		||||
     * @returns DealGetAllResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static getAllDeals(): CancelablePromise<DealGetAllResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/deal/get-all',
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Get Deal By Id
 | 
			
		||||
     * @returns DealSchema Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static getDealById({
 | 
			
		||||
        dealId,
 | 
			
		||||
    }: {
 | 
			
		||||
        dealId: number,
 | 
			
		||||
    }): CancelablePromise<DealSchema> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/deal/get/{deal_id}',
 | 
			
		||||
            path: {
 | 
			
		||||
                'deal_id': dealId,
 | 
			
		||||
            },
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Update General Info
 | 
			
		||||
     * @returns DealUpdateGeneralInfoResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static updateDealGeneralInfo({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: DealUpdateGeneralInfoRequest,
 | 
			
		||||
    }): CancelablePromise<DealUpdateGeneralInfoResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/update-general-info',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Services Add
 | 
			
		||||
     * @returns DealAddServicesResponse Successful Response
 | 
			
		||||
@@ -196,32 +258,80 @@ export class DealService {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Get All
 | 
			
		||||
     * @returns DealGetAllResponse Successful Response
 | 
			
		||||
     * Products Update
 | 
			
		||||
     * @returns DealUpdateProductQuantityResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static getAllDeals(): CancelablePromise<DealGetAllResponse> {
 | 
			
		||||
    public static updateDealProductQuantity({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: DealUpdateProductQuantityRequest,
 | 
			
		||||
    }): CancelablePromise<DealUpdateProductQuantityResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/deal/get-all',
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/products/update-quantity',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Get Deal By Id
 | 
			
		||||
     * @returns DealSchema Successful Response
 | 
			
		||||
     * Products Add
 | 
			
		||||
     * @returns DealAddProductResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static getDealById({
 | 
			
		||||
        dealId,
 | 
			
		||||
    public static addDealProduct({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        dealId: number,
 | 
			
		||||
    }): CancelablePromise<DealSchema> {
 | 
			
		||||
        requestBody: DealAddProductRequest,
 | 
			
		||||
    }): CancelablePromise<DealAddProductResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/deal/get/{deal_id}',
 | 
			
		||||
            path: {
 | 
			
		||||
                'deal_id': dealId,
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/products/add',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Products Delete
 | 
			
		||||
     * @returns DealDeleteProductResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static deleteDealProduct({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: DealDeleteProductRequest,
 | 
			
		||||
    }): CancelablePromise<DealDeleteProductResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/products/delete',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Products Delete
 | 
			
		||||
     * @returns DealDeleteProductsResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static deleteMultipleDealProducts({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: DealDeleteProductsRequest,
 | 
			
		||||
    }): CancelablePromise<DealDeleteProductsResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/deal/products/delete/multiple',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,17 @@
 | 
			
		||||
/* istanbul ignore file */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
import type { ProductAddBarcodeRequest } from '../models/ProductAddBarcodeRequest';
 | 
			
		||||
import type { ProductAddBarcodeResponse } from '../models/ProductAddBarcodeResponse';
 | 
			
		||||
import type { ProductCreateRequest } from '../models/ProductCreateRequest';
 | 
			
		||||
import type { ProductCreateResponse } from '../models/ProductCreateResponse';
 | 
			
		||||
import type { ProductDeleteRequest } from '../models/ProductDeleteRequest';
 | 
			
		||||
import type { ProductDeleteResponse } from '../models/ProductDeleteResponse';
 | 
			
		||||
import type { ProductExistsBarcodeResponse } from '../models/ProductExistsBarcodeResponse';
 | 
			
		||||
import type { ProductGenerateBarcodeRequest } from '../models/ProductGenerateBarcodeRequest';
 | 
			
		||||
import type { ProductGenerateBarcodeResponse } from '../models/ProductGenerateBarcodeResponse';
 | 
			
		||||
import type { ProductGetResponse } from '../models/ProductGetResponse';
 | 
			
		||||
import type { ProductSchema } from '../models/ProductSchema';
 | 
			
		||||
import type { ProductUpdateRequest } from '../models/ProductUpdateRequest';
 | 
			
		||||
import type { ProductUpdateResponse } from '../models/ProductUpdateResponse';
 | 
			
		||||
import type { CancelablePromise } from '../core/CancelablePromise';
 | 
			
		||||
@@ -100,4 +106,89 @@ export class ProductService {
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Get Product By Id
 | 
			
		||||
     * @returns ProductSchema Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static getProductById({
 | 
			
		||||
        productId,
 | 
			
		||||
    }: {
 | 
			
		||||
        productId: number,
 | 
			
		||||
    }): CancelablePromise<ProductSchema> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/product/get-by-id',
 | 
			
		||||
            query: {
 | 
			
		||||
                'product_id': productId,
 | 
			
		||||
            },
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Add Product Barcode
 | 
			
		||||
     * @returns ProductAddBarcodeResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static addProductBarcode({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: ProductAddBarcodeRequest,
 | 
			
		||||
    }): CancelablePromise<ProductAddBarcodeResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/product/barcode/add',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Exists Product Barcode
 | 
			
		||||
     * @returns ProductExistsBarcodeResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static existsProductBarcode({
 | 
			
		||||
        productId,
 | 
			
		||||
        barcode,
 | 
			
		||||
    }: {
 | 
			
		||||
        productId: number,
 | 
			
		||||
        barcode: string,
 | 
			
		||||
    }): CancelablePromise<ProductExistsBarcodeResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'GET',
 | 
			
		||||
            url: '/product/barcode/exists',
 | 
			
		||||
            query: {
 | 
			
		||||
                'product_id': productId,
 | 
			
		||||
                'barcode': barcode,
 | 
			
		||||
            },
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate Product Barcode
 | 
			
		||||
     * @returns ProductGenerateBarcodeResponse Successful Response
 | 
			
		||||
     * @throws ApiError
 | 
			
		||||
     */
 | 
			
		||||
    public static generateProductBarcode({
 | 
			
		||||
        requestBody,
 | 
			
		||||
    }: {
 | 
			
		||||
        requestBody: ProductGenerateBarcodeRequest,
 | 
			
		||||
    }): CancelablePromise<ProductGenerateBarcodeResponse> {
 | 
			
		||||
        return __request(OpenAPI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            url: '/product/barcode/generate',
 | 
			
		||||
            body: requestBody,
 | 
			
		||||
            mediaType: 'application/json',
 | 
			
		||||
            errors: {
 | 
			
		||||
                422: `Validation Error`,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								src/modals/AddBarcodeModal/AddBarcodeModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/modals/AddBarcodeModal/AddBarcodeModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
import {ContextModalProps} from "@mantine/modals";
 | 
			
		||||
import {Button, Flex, rem, TextInput} from "@mantine/core";
 | 
			
		||||
import {useEffect, useState} from "react";
 | 
			
		||||
import {ProductService} from "../../client";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    productId: number;
 | 
			
		||||
    onSubmit: (barcode: string) => void;
 | 
			
		||||
}
 | 
			
		||||
const PrintBarcodeModal = ({
 | 
			
		||||
                               id,
 | 
			
		||||
                               context,
 | 
			
		||||
                               innerProps
 | 
			
		||||
                           }: ContextModalProps<Props>) => {
 | 
			
		||||
    const {productId, onSubmit} = innerProps;
 | 
			
		||||
    const [barcode, setBarcode] = useState<string | undefined>();
 | 
			
		||||
    const [isBarcodeExist, setIsBarcodeExist] = useState<boolean>(true);
 | 
			
		||||
 | 
			
		||||
    const getErrorMessage = () => {
 | 
			
		||||
        if (!barcode) return "Штрихкод не может быть пустым";
 | 
			
		||||
        if (isBarcodeExist) return "Штрихкод уже существует";
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (!barcode) return;
 | 
			
		||||
        ProductService.existsProductBarcode({
 | 
			
		||||
            productId: innerProps.productId,
 | 
			
		||||
            barcode: barcode.trim()
 | 
			
		||||
        }).then((response) => {
 | 
			
		||||
            setIsBarcodeExist(response.exists);
 | 
			
		||||
        })
 | 
			
		||||
    }, [productId, barcode]);
 | 
			
		||||
 | 
			
		||||
    const onSubmitClick = () => {
 | 
			
		||||
        if (!barcode || isBarcodeExist) return;
 | 
			
		||||
        onSubmit(barcode.trim());
 | 
			
		||||
        context.closeModal(id);
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
        <Flex
 | 
			
		||||
            gap={rem(10)}
 | 
			
		||||
            direction={"column"}
 | 
			
		||||
        >
 | 
			
		||||
            <TextInput
 | 
			
		||||
                required
 | 
			
		||||
                error={getErrorMessage()}
 | 
			
		||||
                label={"Штрихкод"}
 | 
			
		||||
                placeholder={"Введите или отсканируйте штрихкод"}
 | 
			
		||||
                value={barcode}
 | 
			
		||||
                onChange={(event) => setBarcode(event.currentTarget.value)}
 | 
			
		||||
 | 
			
		||||
            />
 | 
			
		||||
            <Button
 | 
			
		||||
                onClick={onSubmitClick}
 | 
			
		||||
                disabled={!barcode || isBarcodeExist}
 | 
			
		||||
            >
 | 
			
		||||
                Добавить
 | 
			
		||||
            </Button>
 | 
			
		||||
        </Flex>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default PrintBarcodeModal;
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
.print-only {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media print {
 | 
			
		||||
    .print-only {
 | 
			
		||||
        display: block;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								src/modals/PrintBarcodeModal/PrintBarcodeModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/modals/PrintBarcodeModal/PrintBarcodeModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
import {ContextModalProps, modals} from "@mantine/modals";
 | 
			
		||||
import {Button, Divider, Flex, NumberInput, rem, Select, Spoiler} from "@mantine/core";
 | 
			
		||||
import Barcode from "react-barcode";
 | 
			
		||||
import {useEffect, useRef, useState} from "react";
 | 
			
		||||
import {useReactToPrint} from "react-to-print";
 | 
			
		||||
import {ProductService} from "../../client";
 | 
			
		||||
import styles from "./PrintBarcodeModal.module.css";
 | 
			
		||||
import {useGetProductById} from "../../api/product/useGetProductById.tsx";
 | 
			
		||||
import {notifications} from "../../shared/lib/notifications.ts";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    productId: number;
 | 
			
		||||
    defaultQuantity?: number;
 | 
			
		||||
}
 | 
			
		||||
const PrintBarcodeModal = ({
 | 
			
		||||
                               innerProps
 | 
			
		||||
                           }: ContextModalProps<Props>) => {
 | 
			
		||||
    const {productId, defaultQuantity = 1} = innerProps;
 | 
			
		||||
    const [quantity, setQuantity] = useState(defaultQuantity);
 | 
			
		||||
    const [barcode, setBarcode] = useState<string | undefined>()
 | 
			
		||||
 | 
			
		||||
    const {product, refetch} = useGetProductById(productId);
 | 
			
		||||
 | 
			
		||||
    const barcodeRef = useRef(null);
 | 
			
		||||
    const handlePrint = useReactToPrint({
 | 
			
		||||
        content: () => barcodeRef.current
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onAdd = (newBarcode: string) => {
 | 
			
		||||
        ProductService.addProductBarcode({requestBody: {productId, barcode: newBarcode}})
 | 
			
		||||
            .then(async ({ok, message}) => {
 | 
			
		||||
                notifications.guess(ok, {message});
 | 
			
		||||
            })
 | 
			
		||||
    }
 | 
			
		||||
    const onAddClick = () => {
 | 
			
		||||
        if (!product) return;
 | 
			
		||||
        modals.openContextModal({
 | 
			
		||||
            modal: "addBarcode",
 | 
			
		||||
            title: 'Добавление штрихкода',
 | 
			
		||||
            withCloseButton: true,
 | 
			
		||||
            innerProps: {
 | 
			
		||||
                productId: product.id,
 | 
			
		||||
                onSubmit: onAdd
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const onGenerateClick = () => {
 | 
			
		||||
        if (!product) return;
 | 
			
		||||
        ProductService.generateProductBarcode({requestBody: {productId}})
 | 
			
		||||
            .then(async ({ok, message, barcode}) => {
 | 
			
		||||
                notifications.guess(ok, {message});
 | 
			
		||||
                if (!ok) return;
 | 
			
		||||
                await refetch();
 | 
			
		||||
                setBarcode(barcode);
 | 
			
		||||
            })
 | 
			
		||||
    }
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (!product) return;
 | 
			
		||||
        if (product.barcodes.length === 1)
 | 
			
		||||
            setBarcode(product.barcodes[0]);
 | 
			
		||||
    }, [product]);
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <Flex
 | 
			
		||||
                gap={rem(10)}
 | 
			
		||||
                direction={"column"}
 | 
			
		||||
            >
 | 
			
		||||
                <Select
 | 
			
		||||
                    value={barcode}
 | 
			
		||||
                    onChange={(value) => setBarcode(value || undefined)}
 | 
			
		||||
                    data={product?.barcodes}
 | 
			
		||||
                    label={"Штрихкод"}
 | 
			
		||||
                    placeholder={"Выберите штрихкод"}
 | 
			
		||||
                />
 | 
			
		||||
                <NumberInput
 | 
			
		||||
                    label={"Количество копий"}
 | 
			
		||||
                    placeholder={"Введите количество копий"}
 | 
			
		||||
                    value={quantity}
 | 
			
		||||
                    onChange={(value) => typeof value === "number" && setQuantity(value)}
 | 
			
		||||
                    min={1}
 | 
			
		||||
                />
 | 
			
		||||
                <Spoiler
 | 
			
		||||
                    w={"100%"}
 | 
			
		||||
                    style={{
 | 
			
		||||
                        textAlign: "center",
 | 
			
		||||
                    }}
 | 
			
		||||
                    styles={{control: {width: "100%"}}}
 | 
			
		||||
                    showLabel={"Показать предпросмотр"}
 | 
			
		||||
                    hideLabel={"Скрыть предпросмотр"}
 | 
			
		||||
                    maxHeight={0}>
 | 
			
		||||
                    <div>
 | 
			
		||||
                        {barcode &&
 | 
			
		||||
                            <Barcode value={barcode}/>
 | 
			
		||||
                        }
 | 
			
		||||
                    </div>
 | 
			
		||||
                </Spoiler>
 | 
			
		||||
                <Divider
 | 
			
		||||
                    my={rem(10)}
 | 
			
		||||
                />
 | 
			
		||||
                <Flex direction={"column"} gap={rem(10)}>
 | 
			
		||||
                    <Flex gap={rem(10)}>
 | 
			
		||||
                        <Button
 | 
			
		||||
                            onClick={() => onAddClick()}
 | 
			
		||||
                            variant={"default"}
 | 
			
		||||
                            fullWidth>
 | 
			
		||||
                            Добавить вручную
 | 
			
		||||
                        </Button>
 | 
			
		||||
                        <Button
 | 
			
		||||
                            onClick={() => onGenerateClick()}
 | 
			
		||||
                            variant={"default"}
 | 
			
		||||
                            fullWidth>
 | 
			
		||||
                            Сгенерировать
 | 
			
		||||
                        </Button>
 | 
			
		||||
                    </Flex>
 | 
			
		||||
                    <Button
 | 
			
		||||
                        size={"lg"}
 | 
			
		||||
                        disabled={!barcode}
 | 
			
		||||
                        onClick={() => handlePrint()}
 | 
			
		||||
                    >Печать</Button>
 | 
			
		||||
                </Flex>
 | 
			
		||||
            </Flex>
 | 
			
		||||
            <div className={styles['print-only']} ref={barcodeRef}>
 | 
			
		||||
                {barcode && Array.from({length: quantity}).map((_, index) => (
 | 
			
		||||
                    <Barcode key={index} value={barcode}/>
 | 
			
		||||
                ))}
 | 
			
		||||
            </div>
 | 
			
		||||
        </>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default PrintBarcodeModal;
 | 
			
		||||
@@ -5,6 +5,8 @@ import createProductModal from "../pages/ProductsPage/modals/CreateProductModal/
 | 
			
		||||
import ProductFormModal from "../pages/ClientsPage/modals/ClientFormModal/ClientFormModal.tsx";
 | 
			
		||||
import AddDealServiceModal from "../pages/LeadsPage/modals/AddDealServiceModal.tsx";
 | 
			
		||||
import AddDealProductModal from "../pages/LeadsPage/modals/AddDealProductModal.tsx";
 | 
			
		||||
import PrintBarcodeModal from "./PrintBarcodeModal/PrintBarcodeModal.tsx";
 | 
			
		||||
import AddBarcodeModal from "./AddBarcodeModal/AddBarcodeModal.tsx";
 | 
			
		||||
 | 
			
		||||
export const modals = {
 | 
			
		||||
    enterDeadline: EnterDeadlineModal,
 | 
			
		||||
@@ -13,5 +15,7 @@ export const modals = {
 | 
			
		||||
    createProduct: createProductModal,
 | 
			
		||||
    productFormModal: ProductFormModal,
 | 
			
		||||
    addDealService: AddDealServiceModal,
 | 
			
		||||
    addDealProduct: AddDealProductModal
 | 
			
		||||
    addDealProduct: AddDealProductModal,
 | 
			
		||||
    printBarcode: PrintBarcodeModal,
 | 
			
		||||
    addBarcode: AddBarcodeModal
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import {FC, useState} from "react";
 | 
			
		||||
import {FC} from "react";
 | 
			
		||||
import ClientsTable from "./components/ClientsTable/ClientsTable.tsx";
 | 
			
		||||
import useClientsList from "./hooks/useClientsList.tsx";
 | 
			
		||||
import PageBlock from "../../components/PageBlock/PageBlock.tsx";
 | 
			
		||||
@@ -7,7 +7,6 @@ import {Button} from "@mantine/core";
 | 
			
		||||
import {modals} from "@mantine/modals";
 | 
			
		||||
import {ClientSchema, ClientService} from "../../client";
 | 
			
		||||
import {notifications} from "../../shared/lib/notifications.ts";
 | 
			
		||||
import PlusMinusInput from "../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
			
		||||
 | 
			
		||||
const ClientsPage: FC = () => {
 | 
			
		||||
    const {clients, refetch} = useClientsList();
 | 
			
		||||
@@ -60,7 +59,6 @@ const ClientsPage: FC = () => {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const [a, setA] = useState(5);
 | 
			
		||||
    return (
 | 
			
		||||
        <div className={styles['container']}>
 | 
			
		||||
            <PageBlock>
 | 
			
		||||
@@ -71,12 +69,6 @@ const ClientsPage: FC = () => {
 | 
			
		||||
                    >
 | 
			
		||||
                        Создать клиента
 | 
			
		||||
                    </Button>
 | 
			
		||||
                    <PlusMinusInput onChange={event=>{
 | 
			
		||||
                        console.log(event);
 | 
			
		||||
                        setA(event)
 | 
			
		||||
                    }}
 | 
			
		||||
                                    value={a}
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
            </PageBlock>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,6 @@ const BaseFormModal = <T, >(props: Props<T>) => {
 | 
			
		||||
    const isEditing = 'onChange' in props;
 | 
			
		||||
 | 
			
		||||
    const onSubmit = (values: T) => {
 | 
			
		||||
        console.log('----values');
 | 
			
		||||
        console.log(values)
 | 
			
		||||
        if (isEditing) {
 | 
			
		||||
            props.onChange(values);
 | 
			
		||||
        } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,26 +3,53 @@ import useDealProductsTableColumns from "./columns.tsx";
 | 
			
		||||
import {FC} from "react";
 | 
			
		||||
import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
 | 
			
		||||
import {DealProductSchema} from "../../../../client";
 | 
			
		||||
import {Button, Flex, rem} from "@mantine/core";
 | 
			
		||||
import {ActionIcon, Button, Flex, rem, Tooltip} from "@mantine/core";
 | 
			
		||||
import {MRT_TableOptions} from "mantine-react-table";
 | 
			
		||||
import {modals} from "@mantine/modals";
 | 
			
		||||
import {IconBarcode, IconTrash} from "@tabler/icons-react";
 | 
			
		||||
 | 
			
		||||
type RestProps = {
 | 
			
		||||
    clientId: number;
 | 
			
		||||
    onMultipleDelete?: (items: DealProductSchema[]) => void;
 | 
			
		||||
}
 | 
			
		||||
type Props = CRUDTableProps<DealProductSchema> & RestProps;
 | 
			
		||||
const DealProductsTable: FC<Props> = ({items, clientId}) => {
 | 
			
		||||
    const columns = useDealProductsTableColumns();
 | 
			
		||||
const DealProductsTable: FC<Props> = (props: Props) => {
 | 
			
		||||
    const {items, clientId, onChange, onCreate, onDelete, onMultipleDelete} = props;
 | 
			
		||||
 | 
			
		||||
    const columns = useDealProductsTableColumns({
 | 
			
		||||
        onChange: (product, quantity) => {
 | 
			
		||||
            if (!onChange) return;
 | 
			
		||||
            if (quantity <= 0 && onDelete) {
 | 
			
		||||
                onDelete(product);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            onChange({...product, quantity})
 | 
			
		||||
        },
 | 
			
		||||
        data: items
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onCreateClick = () => {
 | 
			
		||||
        if (!onCreate) return;
 | 
			
		||||
        modals.openContextModal({
 | 
			
		||||
            modal: "addDealProduct",
 | 
			
		||||
            title: "Добавление товара",
 | 
			
		||||
            innerProps: {
 | 
			
		||||
                onCreate: event => console.log(event),
 | 
			
		||||
                onCreate: (product) => onCreate(product as DealProductSchema),
 | 
			
		||||
                clientId
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    const onPrintBarcodeClick = (product: DealProductSchema) => {
 | 
			
		||||
        modals.openContextModal({
 | 
			
		||||
            modal: "printBarcode",
 | 
			
		||||
            title: 'Печать штрихкода',
 | 
			
		||||
            withCloseButton: true,
 | 
			
		||||
            innerProps: {
 | 
			
		||||
                productId: product.product.id,
 | 
			
		||||
                defaultQuantity: product.quantity
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
@@ -30,23 +57,39 @@ const DealProductsTable: FC<Props> = ({items, clientId}) => {
 | 
			
		||||
            data={items}
 | 
			
		||||
            columns={columns}
 | 
			
		||||
            restProps={{
 | 
			
		||||
                renderBottomToolbar: ({}) => (
 | 
			
		||||
                enableBottomToolbar: true,
 | 
			
		||||
                enableRowActions: true,
 | 
			
		||||
                enableRowSelection: true,
 | 
			
		||||
                renderRowActions: ({row}) => (
 | 
			
		||||
                    <Flex gap="md">
 | 
			
		||||
                        <Tooltip label="Удалить">
 | 
			
		||||
                            <ActionIcon onClick={() => onDelete && onDelete(row.original)} variant={"default"}>
 | 
			
		||||
                                <IconTrash/>
 | 
			
		||||
                            </ActionIcon>
 | 
			
		||||
                        </Tooltip>
 | 
			
		||||
                        <Tooltip label="Печать штрихкода">
 | 
			
		||||
                            <ActionIcon onClick={() => onPrintBarcodeClick(row.original)} variant={"default"}>
 | 
			
		||||
                                <IconBarcode/>
 | 
			
		||||
                            </ActionIcon>
 | 
			
		||||
                        </Tooltip>
 | 
			
		||||
                    </Flex>
 | 
			
		||||
                ),
 | 
			
		||||
                renderBottomToolbar: ({table}) => (
 | 
			
		||||
                    <Flex justify={"flex-end"} gap={rem(10)} p={rem(10)}>
 | 
			
		||||
                        {/*{(onMultipleDelete && table.getSelectedRowModel().rows.length > 0) && (*/}
 | 
			
		||||
                        {/*    <Button*/}
 | 
			
		||||
                        {/*        onClick={() => {*/}
 | 
			
		||||
                        {/*            onMultipleDelete(table.getSelectedRowModel().rows.map(row => row.original))*/}
 | 
			
		||||
                        {/*        }}*/}
 | 
			
		||||
                        {/*        variant={"filled"}*/}
 | 
			
		||||
                        {/*        color={"red"}*/}
 | 
			
		||||
                        {/*    >*/}
 | 
			
		||||
                        {/*        Удалить выбранные*/}
 | 
			
		||||
                        {/*    </Button>*/}
 | 
			
		||||
                        {/*)}*/}
 | 
			
		||||
                        {(onMultipleDelete && table.getSelectedRowModel().rows.length > 0) && (
 | 
			
		||||
                            <Button
 | 
			
		||||
                                onClick={() => {
 | 
			
		||||
                                    onMultipleDelete(table.getSelectedRowModel().rows.map(row => row.original))
 | 
			
		||||
                                }}
 | 
			
		||||
                                variant={"filled"}
 | 
			
		||||
                                color={"red"}
 | 
			
		||||
                            >
 | 
			
		||||
                                Удалить выбранные
 | 
			
		||||
                            </Button>
 | 
			
		||||
                        )}
 | 
			
		||||
                        <Button onClick={onCreateClick} variant={"default"}>
 | 
			
		||||
                            Добавить услугу
 | 
			
		||||
                            Добавить товар
 | 
			
		||||
                        </Button>
 | 
			
		||||
 | 
			
		||||
                    </Flex>
 | 
			
		||||
                ),
 | 
			
		||||
            } as MRT_TableOptions<DealProductSchema>}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,65 @@
 | 
			
		||||
import {useMemo} from "react";
 | 
			
		||||
import {MRT_ColumnDef} from "mantine-react-table";
 | 
			
		||||
import {DealProductSchema} from "../../../../client";
 | 
			
		||||
import PlusMinusInput from "../../../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
			
		||||
import {List} from "@mantine/core";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    onChange: (product: DealProductSchema, quantity: number) => void;
 | 
			
		||||
    data: DealProductSchema[];
 | 
			
		||||
}
 | 
			
		||||
const useDealProductsTableColumns = (props: Props) => {
 | 
			
		||||
    const {onChange, data} = props;
 | 
			
		||||
    const totalQuantity = useMemo(() => data.reduce((acc, row) => acc + row.quantity, 0), [data]);
 | 
			
		||||
 | 
			
		||||
const useDealProductsTableColumns = () => {
 | 
			
		||||
    return useMemo<MRT_ColumnDef<DealProductSchema>[]>(() => [
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "products.name",
 | 
			
		||||
            header: "Название"
 | 
			
		||||
            accessorKey: "product.article",
 | 
			
		||||
            header: "Артикул",
 | 
			
		||||
            enableSorting: false,
 | 
			
		||||
            enableColumnActions: false,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "products.article",
 | 
			
		||||
            header: "Артикул"
 | 
			
		||||
            accessorKey: "product.name",
 | 
			
		||||
            header: "Название",
 | 
			
		||||
            enableSorting: false,
 | 
			
		||||
            enableColumnActions: false,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "product.barcodes",
 | 
			
		||||
            header: "Штрихкоды",
 | 
			
		||||
            Cell: ({cell}) => {
 | 
			
		||||
                return (
 | 
			
		||||
                    <List size={"sm"}>
 | 
			
		||||
 | 
			
		||||
                        {cell.getValue<string[]>()?.map(barcode => (
 | 
			
		||||
                            <List.Item key={barcode}>
 | 
			
		||||
                                {barcode}
 | 
			
		||||
                            </List.Item>
 | 
			
		||||
                        ))}
 | 
			
		||||
 | 
			
		||||
                    </List>
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            enableSorting: false,
 | 
			
		||||
            enableColumnActions: false,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "quantity",
 | 
			
		||||
            header: "Количество"
 | 
			
		||||
            header: "Количество",
 | 
			
		||||
            enableSorting: false,
 | 
			
		||||
            enableColumnActions: false,
 | 
			
		||||
            Footer: <>Всего товаров: {totalQuantity} </>,
 | 
			
		||||
            Cell: ({row}) => {
 | 
			
		||||
                return (
 | 
			
		||||
                    <PlusMinusInput
 | 
			
		||||
                        value={row.original.quantity}
 | 
			
		||||
                        onChange={(value) => onChange(row.original, value)}
 | 
			
		||||
                    />
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ], [])
 | 
			
		||||
    ], [onChange, data])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default useDealProductsTableColumns;
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
import {DealStatusHistorySchema} from "../../../../client";
 | 
			
		||||
import {useDealStatusChangeTableColumns} from "./columns.tsx";
 | 
			
		||||
import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
			
		||||
import {FC} from "react";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    items: DealStatusHistorySchema[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const DealStatusChangeTable: FC<Props> = (props: Props) => {
 | 
			
		||||
    const {items} = props;
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <BaseTable
 | 
			
		||||
            data={items}
 | 
			
		||||
            columns={useDealStatusChangeTableColumns()}
 | 
			
		||||
            restProps={{
 | 
			
		||||
                enableRowActions: false,
 | 
			
		||||
                enableColumnActions: false,
 | 
			
		||||
                enableSorting: false,
 | 
			
		||||
                enableBottomToolbar: false,
 | 
			
		||||
                enableColumnFilters: false,
 | 
			
		||||
                enableColumnVisibilityToggle: false,
 | 
			
		||||
            }}
 | 
			
		||||
        />
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
export default DealStatusChangeTable;
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
import {useMemo} from "react";
 | 
			
		||||
import {MRT_ColumnDef} from "mantine-react-table";
 | 
			
		||||
import {DealStatusHistorySchema} from "../../../../client";
 | 
			
		||||
import {DealStatus, DealStatusDictionary} from "../../../../shared/enums/DealStatus.ts";
 | 
			
		||||
 | 
			
		||||
export const useDealStatusChangeTableColumns = () => {
 | 
			
		||||
    return useMemo<MRT_ColumnDef<DealStatusHistorySchema>[]>(() => [
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "changedAt",
 | 
			
		||||
            header: "Дата",
 | 
			
		||||
            accessorFn: (row) => new Date(row.changedAt).toLocaleString('ru-RU'),
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "user.id",
 | 
			
		||||
            header: "ID пользователя",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "fromStatus",
 | 
			
		||||
            header: "Из статуса",
 | 
			
		||||
            accessorFn: (row) => DealStatusDictionary[row.fromStatus as DealStatus],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            accessorKey: "toStatus",
 | 
			
		||||
            header: "В статус",
 | 
			
		||||
            accessorFn: (row) => DealStatusDictionary[row.toStatus as DealStatus],
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    ], []);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +1,15 @@
 | 
			
		||||
import {Drawer, Text} from "@mantine/core";
 | 
			
		||||
import {Box, Drawer, rem, Tabs, Text} from "@mantine/core";
 | 
			
		||||
import {FC, useRef} from "react";
 | 
			
		||||
import DealServicesTable from "../../components/DealServicesTable/DealServicesTable.tsx";
 | 
			
		||||
import {useDealPageContext} from "../../contexts/DealPageContext.tsx";
 | 
			
		||||
import {DealService, DealServiceSchema} from "../../../../client";
 | 
			
		||||
import {DealProductSchema, DealService, DealServiceSchema} from "../../../../client";
 | 
			
		||||
import {notifications} from "../../../../shared/lib/notifications.ts";
 | 
			
		||||
import {modals} from "@mantine/modals";
 | 
			
		||||
import {BaseTableRef} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
			
		||||
import DealProductsTable from "../../components/DealProductsTable/DealProductsTable.tsx";
 | 
			
		||||
import {IconBarcode, IconBox, IconCalendarUser, IconSettings} from "@tabler/icons-react";
 | 
			
		||||
import DealStatusChangeTable from "../../components/DealStatusChangeTable/DealStatusChangeTable.tsx";
 | 
			
		||||
import DealEditDrawerGeneralTab from "./tabs/DealEditDrawerGeneralTab.tsx";
 | 
			
		||||
 | 
			
		||||
const useDealServicesTableState = () => {
 | 
			
		||||
    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
			
		||||
@@ -30,7 +33,6 @@ const useDealServicesTableState = () => {
 | 
			
		||||
                .then(setSelectedDeal)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const onServiceDelete = (service: DealServiceSchema) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        modals.openConfirmModal({
 | 
			
		||||
@@ -68,7 +70,6 @@ const useDealServicesTableState = () => {
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const onServiceCreate = (service: DealServiceSchema) => {
 | 
			
		||||
        console.log('-------Drawer')
 | 
			
		||||
        console.log(service);
 | 
			
		||||
@@ -88,7 +89,6 @@ const useDealServicesTableState = () => {
 | 
			
		||||
                .then(setSelectedDeal)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const onsServiceMultipleDelete = (items: DealServiceSchema[]) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        modals.openConfirmModal({
 | 
			
		||||
@@ -152,27 +152,158 @@ const DealEditDrawerServicesTable = () => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const useDealProductTableState = () => {
 | 
			
		||||
    const {selectedDeal} = useDealPageContext();
 | 
			
		||||
    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
			
		||||
 | 
			
		||||
    const onProductUpdate = (product: DealProductSchema) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        DealService.updateDealProductQuantity({
 | 
			
		||||
            requestBody: {
 | 
			
		||||
                dealId: selectedDeal.id,
 | 
			
		||||
                productId: product.product.id,
 | 
			
		||||
                quantity: product.quantity
 | 
			
		||||
            }
 | 
			
		||||
        }).then(async ({ok, message}) => {
 | 
			
		||||
            if (!ok) {
 | 
			
		||||
                notifications.guess(ok, {message});
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await DealService.getDealById({dealId: selectedDeal.id})
 | 
			
		||||
                .then(setSelectedDeal)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    const onProductDelete = (product: DealProductSchema) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        modals.openConfirmModal({
 | 
			
		||||
            title: "Удаление товара",
 | 
			
		||||
            children: (
 | 
			
		||||
                <>
 | 
			
		||||
                    <Text>
 | 
			
		||||
                        Вы уверены, что хотите удалить товар:
 | 
			
		||||
                    </Text>
 | 
			
		||||
                    <Text>
 | 
			
		||||
                        {product.product.name}?
 | 
			
		||||
                    </Text>
 | 
			
		||||
 | 
			
		||||
                </>
 | 
			
		||||
 | 
			
		||||
            ),
 | 
			
		||||
            onConfirm: () => {
 | 
			
		||||
                DealService.deleteDealProduct({
 | 
			
		||||
                    requestBody: {
 | 
			
		||||
                        dealId: selectedDeal.id,
 | 
			
		||||
                        productId: product.product.id
 | 
			
		||||
                    }
 | 
			
		||||
                }).then(async ({ok, message}) => {
 | 
			
		||||
                    if (!ok) {
 | 
			
		||||
                        notifications.guess(ok, {message});
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    await DealService.getDealById({dealId: selectedDeal.id})
 | 
			
		||||
                        .then(setSelectedDeal)
 | 
			
		||||
                })
 | 
			
		||||
            },
 | 
			
		||||
            labels: {
 | 
			
		||||
                cancel: "Отмена",
 | 
			
		||||
                confirm: "Удалить"
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    const onProductCreate = (product: DealProductSchema) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        DealService.addDealProduct({
 | 
			
		||||
            requestBody: {
 | 
			
		||||
                dealId: selectedDeal.id,
 | 
			
		||||
                productId: product.product.id,
 | 
			
		||||
                quantity: product.quantity
 | 
			
		||||
            }
 | 
			
		||||
        }).then(async ({ok, message}) => {
 | 
			
		||||
            if (!ok) {
 | 
			
		||||
                notifications.guess(ok, {message});
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await DealService.getDealById({dealId: selectedDeal.id})
 | 
			
		||||
                .then(setSelectedDeal)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    const onProductMultipleDelete = (items: DealProductSchema[]) => {
 | 
			
		||||
        if (!selectedDeal) return;
 | 
			
		||||
        modals.openConfirmModal({
 | 
			
		||||
            title: "Удаление товаров",
 | 
			
		||||
            children: (
 | 
			
		||||
                <>
 | 
			
		||||
                    <Text>
 | 
			
		||||
                        Вы уверены, что хотите удалить выбранные товары?
 | 
			
		||||
                    </Text>
 | 
			
		||||
                </>
 | 
			
		||||
            ),
 | 
			
		||||
            onConfirm: () => {
 | 
			
		||||
                DealService.deleteMultipleDealProducts({
 | 
			
		||||
                    requestBody: {
 | 
			
		||||
                        dealId: selectedDeal.id,
 | 
			
		||||
                        productIds: items.map(item => item.product.id)
 | 
			
		||||
                    }
 | 
			
		||||
                }).then(async ({ok, message}) => {
 | 
			
		||||
                    if (!ok) {
 | 
			
		||||
                        notifications.guess(ok, {message});
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    await DealService.getDealById({dealId: selectedDeal.id})
 | 
			
		||||
                        .then(setSelectedDeal)
 | 
			
		||||
                })
 | 
			
		||||
            },
 | 
			
		||||
            labels: {
 | 
			
		||||
                cancel: "Отмена",
 | 
			
		||||
                confirm: "Удалить"
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        clientId: selectedDeal?.clientId || -1,
 | 
			
		||||
        products: selectedDeal?.products || []
 | 
			
		||||
        products: selectedDeal?.products || [],
 | 
			
		||||
        onProductUpdate,
 | 
			
		||||
        onProductDelete,
 | 
			
		||||
        onProductCreate,
 | 
			
		||||
        onProductMultipleDelete
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const DealEditDrawerProductsTable = () => {
 | 
			
		||||
    const {
 | 
			
		||||
        products,
 | 
			
		||||
        clientId
 | 
			
		||||
        clientId,
 | 
			
		||||
        onProductUpdate,
 | 
			
		||||
        onProductDelete,
 | 
			
		||||
        onProductCreate,
 | 
			
		||||
        onProductMultipleDelete,
 | 
			
		||||
    } = useDealProductTableState();
 | 
			
		||||
    return (
 | 
			
		||||
        <DealProductsTable
 | 
			
		||||
            clientId={clientId}
 | 
			
		||||
            items={products}
 | 
			
		||||
            onChange={onProductUpdate}
 | 
			
		||||
            onMultipleDelete={onProductMultipleDelete}
 | 
			
		||||
            onDelete={onProductDelete}
 | 
			
		||||
            onCreate={onProductCreate}
 | 
			
		||||
 | 
			
		||||
        />
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const useDealStatusChangeState = () => {
 | 
			
		||||
    const {selectedDeal} = useDealPageContext();
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        statusHistory: selectedDeal?.statusHistory || []
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
const DealEditDrawerStatusChangeTable = () => {
 | 
			
		||||
    const {statusHistory} = useDealStatusChangeState();
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <DealStatusChangeTable
 | 
			
		||||
            items={statusHistory}
 | 
			
		||||
        />)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const useDealEditDrawerState = () => {
 | 
			
		||||
    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
			
		||||
    return {
 | 
			
		||||
@@ -189,9 +320,55 @@ const DealEditDrawer: FC = () => {
 | 
			
		||||
            size={"95%"}
 | 
			
		||||
            position={"right"}
 | 
			
		||||
            onClose={onClose}
 | 
			
		||||
            opened={isVisible}>
 | 
			
		||||
            <DealEditDrawerServicesTable/>
 | 
			
		||||
            <DealEditDrawerProductsTable/>
 | 
			
		||||
            removeScrollProps={{allowPinchZoom: true}}
 | 
			
		||||
            withCloseButton={false}
 | 
			
		||||
            opened={isVisible}
 | 
			
		||||
            styles={{body: {height: '100%'}}}
 | 
			
		||||
        >
 | 
			
		||||
            <Tabs
 | 
			
		||||
                defaultValue={"general"}
 | 
			
		||||
                h={'100%'}
 | 
			
		||||
                variant={"outline"}
 | 
			
		||||
                orientation={"vertical"}>
 | 
			
		||||
                <Tabs.List
 | 
			
		||||
                >
 | 
			
		||||
                    <Tabs.Tab value={"general"} leftSection={<IconSettings/>}>
 | 
			
		||||
                        Общее
 | 
			
		||||
                    </Tabs.Tab>
 | 
			
		||||
                    <Tabs.Tab value={"history"} leftSection={<IconCalendarUser/>}>
 | 
			
		||||
                        История
 | 
			
		||||
                    </Tabs.Tab>
 | 
			
		||||
                    <Tabs.Tab value={"services"} leftSection={<IconBox/>}>
 | 
			
		||||
                        Услуги
 | 
			
		||||
                    </Tabs.Tab>
 | 
			
		||||
                    <Tabs.Tab value={"products"} leftSection={<IconBarcode/>}>
 | 
			
		||||
                        Товары
 | 
			
		||||
                    </Tabs.Tab>
 | 
			
		||||
                </Tabs.List>
 | 
			
		||||
                <Tabs.Panel value={"general"}>
 | 
			
		||||
                    <Box h={"100%"} w={"100%"} p={rem(10)}>
 | 
			
		||||
                        <DealEditDrawerGeneralTab/>
 | 
			
		||||
                    </Box>
 | 
			
		||||
                </Tabs.Panel>
 | 
			
		||||
                <Tabs.Panel value={"history"}>
 | 
			
		||||
                    <Box p={rem(10)}>
 | 
			
		||||
                        <DealEditDrawerStatusChangeTable/>
 | 
			
		||||
                    </Box>
 | 
			
		||||
                </Tabs.Panel>
 | 
			
		||||
                <Tabs.Panel value={"services"}>
 | 
			
		||||
                    <Box p={rem(10)}>
 | 
			
		||||
 | 
			
		||||
                        <DealEditDrawerServicesTable/>
 | 
			
		||||
                    </Box>
 | 
			
		||||
                </Tabs.Panel>
 | 
			
		||||
                <Tabs.Panel value={"products"}>
 | 
			
		||||
                    <Box p={rem(10)}>
 | 
			
		||||
 | 
			
		||||
                        <DealEditDrawerProductsTable/>
 | 
			
		||||
                    </Box>
 | 
			
		||||
 | 
			
		||||
                </Tabs.Panel>
 | 
			
		||||
            </Tabs>
 | 
			
		||||
        </Drawer>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,148 @@
 | 
			
		||||
import {FC} from "react";
 | 
			
		||||
import {useDealPageContext} from "../../../contexts/DealPageContext.tsx";
 | 
			
		||||
import {Button, Checkbox, Fieldset, Flex, Group, rem, TextInput} from "@mantine/core";
 | 
			
		||||
import {useForm} from "@mantine/form";
 | 
			
		||||
import {ClientService, DealSchema, DealService} from "../../../../../client";
 | 
			
		||||
import {DealStatus, DealStatusDictionary} from "../../../../../shared/enums/DealStatus.ts";
 | 
			
		||||
import {isEqual} from "lodash";
 | 
			
		||||
import {notifications} from "../../../../../shared/lib/notifications.ts";
 | 
			
		||||
import {useQueryClient} from "@tanstack/react-query";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
    deal: DealSchema
 | 
			
		||||
}
 | 
			
		||||
type FormType = Omit<DealSchema, 'statusHistory' | 'services' | 'products'>
 | 
			
		||||
 | 
			
		||||
const Content: FC<Props> = ({deal}) => {
 | 
			
		||||
    const {setSelectedDeal} = useDealPageContext();
 | 
			
		||||
    const queryClient = useQueryClient();
 | 
			
		||||
 | 
			
		||||
    const initialValues: FormType = deal;
 | 
			
		||||
    const form = useForm<FormType>(
 | 
			
		||||
        {
 | 
			
		||||
            initialValues: initialValues,
 | 
			
		||||
            validate: {
 | 
			
		||||
                name: (value: string) => value.length > 0 ? null : 'Название сделки не может быть пустым'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    const updateDealInfo = async (values: FormType) => {
 | 
			
		||||
        return DealService.updateDealGeneralInfo({
 | 
			
		||||
            requestBody: {
 | 
			
		||||
                dealId: deal.id,
 | 
			
		||||
                data: values
 | 
			
		||||
            }
 | 
			
		||||
        }).then(({ok, message}) => {
 | 
			
		||||
            notifications.guess(ok, {message});
 | 
			
		||||
            if (!ok) return;
 | 
			
		||||
            DealService.getDealById({dealId: deal.id})
 | 
			
		||||
                .then((data) => {
 | 
			
		||||
                    setSelectedDeal(data);
 | 
			
		||||
                    form.setInitialValues(data);
 | 
			
		||||
                    queryClient.invalidateQueries({
 | 
			
		||||
                        queryKey: ['getDealSummaries']
 | 
			
		||||
                    })
 | 
			
		||||
                })
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    const updateClientInfo = async (values: FormType) => {
 | 
			
		||||
        return ClientService.updateClient({
 | 
			
		||||
            requestBody: {
 | 
			
		||||
                data: values.client
 | 
			
		||||
            }
 | 
			
		||||
        }).then(({ok, message}) =>
 | 
			
		||||
            notifications.guess(ok, {message}));
 | 
			
		||||
    }
 | 
			
		||||
    const handleSubmit = async (values: FormType) => {
 | 
			
		||||
        // Updating client info if there changes
 | 
			
		||||
        if (!isEqual(values.client, deal.client)) {
 | 
			
		||||
            await updateClientInfo(values);
 | 
			
		||||
        }
 | 
			
		||||
        // updating deal info
 | 
			
		||||
        await updateDealInfo(values);
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
        <form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
 | 
			
		||||
            <Fieldset legend={"Общие параметры"}>
 | 
			
		||||
                <Flex direction={"column"} gap={rem(10)}>
 | 
			
		||||
                    <TextInput
 | 
			
		||||
                        placeholder={"Название сделки"}
 | 
			
		||||
                        label={"Название сделки"}
 | 
			
		||||
                        {...form.getInputProps('name')}
 | 
			
		||||
                    />
 | 
			
		||||
                    <TextInput
 | 
			
		||||
                        disabled
 | 
			
		||||
                        placeholder={"Дата создания"}
 | 
			
		||||
                        label={"Дата создания"}
 | 
			
		||||
                        value={new Date(deal.createdAt).toLocaleString('ru-RU')}
 | 
			
		||||
                    />
 | 
			
		||||
                    <TextInput
 | 
			
		||||
                        disabled
 | 
			
		||||
                        placeholder={"Текущий статус"}
 | 
			
		||||
                        label={"Текущий статус"}
 | 
			
		||||
                        value={DealStatusDictionary[deal.currentStatus as DealStatus]}/>
 | 
			
		||||
                    <Checkbox
 | 
			
		||||
                        label={"Сделка завершена"}
 | 
			
		||||
                        {...form.getInputProps('isCompleted')}
 | 
			
		||||
                    />
 | 
			
		||||
 | 
			
		||||
                    <Checkbox
 | 
			
		||||
                        label={"Сделка удалена"}
 | 
			
		||||
                        {...form.getInputProps('isDeleted')}
 | 
			
		||||
                    />
 | 
			
		||||
 | 
			
		||||
                </Flex>
 | 
			
		||||
            </Fieldset>
 | 
			
		||||
            <Fieldset legend={"Клиент"}>
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    disabled
 | 
			
		||||
                    placeholder={"Название"}
 | 
			
		||||
                    label={"Название"}
 | 
			
		||||
                    value={deal.client.name}
 | 
			
		||||
                />
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    placeholder={"Введите телефон"}
 | 
			
		||||
                    label={"Телефон клиента"}
 | 
			
		||||
                    {...form.getInputProps('client.details.phoneNumber')}
 | 
			
		||||
                />
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    placeholder={"Введите email"}
 | 
			
		||||
                    label={"Email"}
 | 
			
		||||
                    {...form.getInputProps('client.details.email')}
 | 
			
		||||
                />
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    placeholder={"Введите адрес"}
 | 
			
		||||
                    label={"Адрес"}
 | 
			
		||||
                    {...form.getInputProps('client.details.address')}
 | 
			
		||||
                />
 | 
			
		||||
                <TextInput
 | 
			
		||||
                    placeholder={"Введите ИНН"}
 | 
			
		||||
                    label={"ИНН"}
 | 
			
		||||
                    {...form.getInputProps('client.details.inn')}
 | 
			
		||||
                />
 | 
			
		||||
            </Fieldset>
 | 
			
		||||
            <Group justify={"flex-end"} mt={"md"}>
 | 
			
		||||
                <Button
 | 
			
		||||
                    color={"red"}
 | 
			
		||||
                    type={"reset"}
 | 
			
		||||
                    disabled={isEqual(initialValues, form.values)}
 | 
			
		||||
                    onClick={() => form.reset()}
 | 
			
		||||
                >Отменить изменения</Button>
 | 
			
		||||
                <Button
 | 
			
		||||
                    variant={"default"}
 | 
			
		||||
                    type={"submit"}
 | 
			
		||||
                    disabled={isEqual(initialValues, form.values)}
 | 
			
		||||
                >Сохранить изменения</Button>
 | 
			
		||||
            </Group>
 | 
			
		||||
        </form>
 | 
			
		||||
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
const DealEditDrawerGeneralTab: FC = () => {
 | 
			
		||||
    const {selectedDeal} = useDealPageContext();
 | 
			
		||||
    if (!selectedDeal) return <>No deal selected</>;
 | 
			
		||||
    return (
 | 
			
		||||
        <Content deal={selectedDeal}/>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
export default DealEditDrawerGeneralTab;
 | 
			
		||||
@@ -29,7 +29,6 @@ const AddDealProductModal = ({
 | 
			
		||||
        context.closeContextModal(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <BaseFormModal
 | 
			
		||||
            {...innerProps}
 | 
			
		||||
@@ -39,10 +38,10 @@ const AddDealProductModal = ({
 | 
			
		||||
            <BaseFormModal.Body>
 | 
			
		||||
                <>
 | 
			
		||||
                    <ProductSelect
 | 
			
		||||
                        placeholder={"Выберите услугу"}
 | 
			
		||||
                        label={"Услуга"}
 | 
			
		||||
                        placeholder={"Выберите товар"}
 | 
			
		||||
                        label={"Товар"}
 | 
			
		||||
                        clientId={innerProps.clientId}
 | 
			
		||||
                        {...form.getInputProps('service')}
 | 
			
		||||
                        {...form.getInputProps('product')}
 | 
			
		||||
                    />
 | 
			
		||||
                    <NumberInput
 | 
			
		||||
                        placeholder={"Введите количество"}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
			
		||||
import {MRT_TableOptions} from "mantine-react-table";
 | 
			
		||||
import {useProductsTableColumns} from "./columns.tsx";
 | 
			
		||||
import {ActionIcon, Flex, Tooltip} from "@mantine/core";
 | 
			
		||||
import {IconEdit, IconTrash} from "@tabler/icons-react";
 | 
			
		||||
import {IconBarcode, IconEdit, IconTrash} from "@tabler/icons-react";
 | 
			
		||||
import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
 | 
			
		||||
import {modals} from "@mantine/modals";
 | 
			
		||||
 | 
			
		||||
@@ -23,6 +23,16 @@ const ProductsTable: FC<CRUDTableProps<ProductSchema>> = ({items, onDelete, onCh
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    const onPrintBarcodeClick = (product: ProductSchema) => {
 | 
			
		||||
        modals.openContextModal({
 | 
			
		||||
            modal: "printBarcode",
 | 
			
		||||
            title: 'Печать штрихкода',
 | 
			
		||||
            withCloseButton: true,
 | 
			
		||||
            innerProps: {
 | 
			
		||||
                productId: product.id
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
        <BaseTable
 | 
			
		||||
            ref={tableRef}
 | 
			
		||||
@@ -33,6 +43,13 @@ const ProductsTable: FC<CRUDTableProps<ProductSchema>> = ({items, onDelete, onCh
 | 
			
		||||
                enableRowActions: true,
 | 
			
		||||
                renderRowActions: ({row}) => (
 | 
			
		||||
                    <Flex gap="md">
 | 
			
		||||
                        <Tooltip label="Печать штрихкода">
 | 
			
		||||
                            <ActionIcon
 | 
			
		||||
                                onClick={() => onPrintBarcodeClick(row.original)}
 | 
			
		||||
                                variant={"default"}>
 | 
			
		||||
                                <IconBarcode/>
 | 
			
		||||
                            </ActionIcon>
 | 
			
		||||
                        </Tooltip>
 | 
			
		||||
                        <Tooltip label="Редактировать">
 | 
			
		||||
                            <ActionIcon
 | 
			
		||||
                                onClick={() => onEditClick(row.original)}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ import {notifications} from "../../../shared/lib/notifications.ts";
 | 
			
		||||
import {CreateProductRequest} from "../types.ts";
 | 
			
		||||
import {ProductSchema, ProductService} from "../../../client";
 | 
			
		||||
import useProductsList from "../hooks/useProductsList.tsx";
 | 
			
		||||
import ProductSelect from "../../../components/ProductSelect/ProductSelect.tsx";
 | 
			
		||||
 | 
			
		||||
export const ProductsPage: FC = () => {
 | 
			
		||||
    const [clientId, setClientId] = useState(-1);
 | 
			
		||||
@@ -90,11 +89,7 @@ export const ProductsPage: FC = () => {
 | 
			
		||||
                            onClick={() => onCreateProductClick()}
 | 
			
		||||
                            variant={"default"}
 | 
			
		||||
                        >Создать</Button>
 | 
			
		||||
                        <ProductSelect
 | 
			
		||||
                            onChange={event => console.log(event)}
 | 
			
		||||
                            clientId={8}
 | 
			
		||||
                            limit={10}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                    </div>
 | 
			
		||||
                </PageBlock>
 | 
			
		||||
                <PageBlock>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import {createLazyFileRoute} from "@tanstack/react-router";
 | 
			
		||||
import {Button} from "@mantine/core";
 | 
			
		||||
import {notifications} from "@mantine/notifications";
 | 
			
		||||
import {Button, Text} from "@mantine/core";
 | 
			
		||||
import {modals} from "@mantine/modals";
 | 
			
		||||
 | 
			
		||||
export const Route = createLazyFileRoute('/test')({
 | 
			
		||||
    component: TestPage
 | 
			
		||||
@@ -8,11 +8,28 @@ export const Route = createLazyFileRoute('/test')({
 | 
			
		||||
 | 
			
		||||
function TestPage() {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <Button onClick={() => {
 | 
			
		||||
                notifications.show({title: "test", message: "хуй"})
 | 
			
		||||
            }}>TEST</Button>
 | 
			
		||||
 | 
			
		||||
        </>
 | 
			
		||||
    )
 | 
			
		||||
        <Button
 | 
			
		||||
            onClick={() =>
 | 
			
		||||
                modals.openConfirmModal({
 | 
			
		||||
                    title: 'Please confirm your action',
 | 
			
		||||
                    closeOnConfirm: false,
 | 
			
		||||
                    labels: {confirm: 'Next modal', cancel: 'Close modal'},
 | 
			
		||||
                    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>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
@@ -10,4 +10,13 @@ export enum DealStatus {
 | 
			
		||||
 | 
			
		||||
export const getDealStatusByName = (name: string): DealStatus => {
 | 
			
		||||
    return DealStatus[name as keyof typeof DealStatus];
 | 
			
		||||
}
 | 
			
		||||
export const DealStatusDictionary = {
 | 
			
		||||
    [DealStatus.CREATED]: "Создан",
 | 
			
		||||
    [DealStatus.AWAITING_ACCEPTANCE]: "Ожидает приемки",
 | 
			
		||||
    [DealStatus.PACKAGING]: "Упаковка",
 | 
			
		||||
    [DealStatus.AWAITING_SHIPMENT]: "Ожидает отгрузки",
 | 
			
		||||
    [DealStatus.AWAITING_PAYMENT]: "Ожидает оплаты",
 | 
			
		||||
    [DealStatus.COMPLETED]: "Завершена",
 | 
			
		||||
    [DealStatus.CANCELLED]: "Отменена",
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user