crap
This commit is contained in:
		@@ -19,16 +19,26 @@ export type { ClientSchema } from './models/ClientSchema';
 | 
				
			|||||||
export type { ClientUpdateDetailsRequest } from './models/ClientUpdateDetailsRequest';
 | 
					export type { ClientUpdateDetailsRequest } from './models/ClientUpdateDetailsRequest';
 | 
				
			||||||
export type { ClientUpdateRequest } from './models/ClientUpdateRequest';
 | 
					export type { ClientUpdateRequest } from './models/ClientUpdateRequest';
 | 
				
			||||||
export type { ClientUpdateResponse } from './models/ClientUpdateResponse';
 | 
					export type { ClientUpdateResponse } from './models/ClientUpdateResponse';
 | 
				
			||||||
 | 
					export type { DealAddServiceRequest } from './models/DealAddServiceRequest';
 | 
				
			||||||
 | 
					export type { DealAddServiceResponse } from './models/DealAddServiceResponse';
 | 
				
			||||||
export type { DealAddServicesRequest } from './models/DealAddServicesRequest';
 | 
					export type { DealAddServicesRequest } from './models/DealAddServicesRequest';
 | 
				
			||||||
export type { DealAddServicesResponse } from './models/DealAddServicesResponse';
 | 
					export type { DealAddServicesResponse } from './models/DealAddServicesResponse';
 | 
				
			||||||
export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
 | 
					export type { DealChangeStatusRequest } from './models/DealChangeStatusRequest';
 | 
				
			||||||
export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
 | 
					export type { DealChangeStatusResponse } from './models/DealChangeStatusResponse';
 | 
				
			||||||
export type { DealCreateRequest } from './models/DealCreateRequest';
 | 
					export type { DealCreateRequest } from './models/DealCreateRequest';
 | 
				
			||||||
 | 
					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 { DealGetAllResponse } from './models/DealGetAllResponse';
 | 
				
			||||||
export type { DealQuickCreateRequest } from './models/DealQuickCreateRequest';
 | 
					export type { DealQuickCreateRequest } from './models/DealQuickCreateRequest';
 | 
				
			||||||
export type { DealQuickCreateResponse } from './models/DealQuickCreateResponse';
 | 
					export type { DealQuickCreateResponse } from './models/DealQuickCreateResponse';
 | 
				
			||||||
 | 
					export type { DealSchema } from './models/DealSchema';
 | 
				
			||||||
export type { DealServiceSchema } from './models/DealServiceSchema';
 | 
					export type { DealServiceSchema } from './models/DealServiceSchema';
 | 
				
			||||||
export type { DealSummary } from './models/DealSummary';
 | 
					export type { DealSummary } from './models/DealSummary';
 | 
				
			||||||
export type { DealSummaryResponse } from './models/DealSummaryResponse';
 | 
					export type { DealSummaryResponse } from './models/DealSummaryResponse';
 | 
				
			||||||
 | 
					export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest';
 | 
				
			||||||
 | 
					export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse';
 | 
				
			||||||
export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
					export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
				
			||||||
export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
 | 
					export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
 | 
				
			||||||
export type { ProductCreateRequest } from './models/ProductCreateRequest';
 | 
					export type { ProductCreateRequest } from './models/ProductCreateRequest';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/client/models/DealAddServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealAddServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealAddServiceRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    serviceId: number;
 | 
				
			||||||
 | 
					    quantity: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealAddServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealAddServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealAddServiceResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealDeleteServiceRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    serviceId: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealDeleteServiceResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteServicesRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteServicesRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealDeleteServicesRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    serviceIds: Array<number>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealDeleteServicesResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealDeleteServicesResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealDeleteServicesResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealGetAllResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealGetAllResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { DealSchema } from './DealSchema';
 | 
				
			||||||
 | 
					export type DealGetAllResponse = {
 | 
				
			||||||
 | 
					    deals: Array<DealSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/client/models/DealSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/client/models/DealSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { DealServiceSchema } from './DealServiceSchema';
 | 
				
			||||||
 | 
					export type DealSchema = {
 | 
				
			||||||
 | 
					    id: number;
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					    clientId: number;
 | 
				
			||||||
 | 
					    createdAt: string;
 | 
				
			||||||
 | 
					    currentStatus: number;
 | 
				
			||||||
 | 
					    services: Array<DealServiceSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,8 +2,9 @@
 | 
				
			|||||||
/* istanbul ignore file */
 | 
					/* istanbul ignore file */
 | 
				
			||||||
/* tslint:disable */
 | 
					/* tslint:disable */
 | 
				
			||||||
/* eslint-disable */
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { ServiceSchema } from './ServiceSchema';
 | 
				
			||||||
export type DealServiceSchema = {
 | 
					export type DealServiceSchema = {
 | 
				
			||||||
    id: number;
 | 
					    service: ServiceSchema;
 | 
				
			||||||
    quantity: number;
 | 
					    quantity: number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/client/models/DealUpdateServiceQuantityRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealUpdateServiceQuantityRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealUpdateServiceQuantityRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    serviceId: number;
 | 
				
			||||||
 | 
					    quantity: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealUpdateServiceQuantityResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealUpdateServiceQuantityResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealUpdateServiceQuantityResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,14 +2,24 @@
 | 
				
			|||||||
/* istanbul ignore file */
 | 
					/* istanbul ignore file */
 | 
				
			||||||
/* tslint:disable */
 | 
					/* tslint:disable */
 | 
				
			||||||
/* eslint-disable */
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { DealAddServiceRequest } from '../models/DealAddServiceRequest';
 | 
				
			||||||
 | 
					import type { DealAddServiceResponse } from '../models/DealAddServiceResponse';
 | 
				
			||||||
import type { DealAddServicesRequest } from '../models/DealAddServicesRequest';
 | 
					import type { DealAddServicesRequest } from '../models/DealAddServicesRequest';
 | 
				
			||||||
import type { DealAddServicesResponse } from '../models/DealAddServicesResponse';
 | 
					import type { DealAddServicesResponse } from '../models/DealAddServicesResponse';
 | 
				
			||||||
import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
 | 
					import type { DealChangeStatusRequest } from '../models/DealChangeStatusRequest';
 | 
				
			||||||
import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
 | 
					import type { DealChangeStatusResponse } from '../models/DealChangeStatusResponse';
 | 
				
			||||||
import type { DealCreateRequest } from '../models/DealCreateRequest';
 | 
					import type { DealCreateRequest } from '../models/DealCreateRequest';
 | 
				
			||||||
 | 
					import type { DealDeleteServiceRequest } from '../models/DealDeleteServiceRequest';
 | 
				
			||||||
 | 
					import type { DealDeleteServiceResponse } from '../models/DealDeleteServiceResponse';
 | 
				
			||||||
 | 
					import type { DealDeleteServicesRequest } from '../models/DealDeleteServicesRequest';
 | 
				
			||||||
 | 
					import type { DealDeleteServicesResponse } from '../models/DealDeleteServicesResponse';
 | 
				
			||||||
 | 
					import type { DealGetAllResponse } from '../models/DealGetAllResponse';
 | 
				
			||||||
import type { DealQuickCreateRequest } from '../models/DealQuickCreateRequest';
 | 
					import type { DealQuickCreateRequest } from '../models/DealQuickCreateRequest';
 | 
				
			||||||
import type { DealQuickCreateResponse } from '../models/DealQuickCreateResponse';
 | 
					import type { DealQuickCreateResponse } from '../models/DealQuickCreateResponse';
 | 
				
			||||||
 | 
					import type { DealSchema } from '../models/DealSchema';
 | 
				
			||||||
import type { DealSummaryResponse } from '../models/DealSummaryResponse';
 | 
					import type { DealSummaryResponse } from '../models/DealSummaryResponse';
 | 
				
			||||||
 | 
					import type { DealUpdateServiceQuantityRequest } from '../models/DealUpdateServiceQuantityRequest';
 | 
				
			||||||
 | 
					import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
				
			||||||
import type { CancelablePromise } from '../core/CancelablePromise';
 | 
					import type { CancelablePromise } from '../core/CancelablePromise';
 | 
				
			||||||
import { OpenAPI } from '../core/OpenAPI';
 | 
					import { OpenAPI } from '../core/OpenAPI';
 | 
				
			||||||
import { request as __request } from '../core/request';
 | 
					import { request as __request } from '../core/request';
 | 
				
			||||||
@@ -90,11 +100,31 @@ export class DealService {
 | 
				
			|||||||
     * @returns DealAddServicesResponse Successful Response
 | 
					     * @returns DealAddServicesResponse Successful Response
 | 
				
			||||||
     * @throws ApiError
 | 
					     * @throws ApiError
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static servicesAddDealServicesAddPost({
 | 
					    public static addMultipleDealServices({
 | 
				
			||||||
        requestBody,
 | 
					        requestBody,
 | 
				
			||||||
    }: {
 | 
					    }: {
 | 
				
			||||||
        requestBody: DealAddServicesRequest,
 | 
					        requestBody: DealAddServicesRequest,
 | 
				
			||||||
    }): CancelablePromise<DealAddServicesResponse> {
 | 
					    }): CancelablePromise<DealAddServicesResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/services/add/multiple',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Services Add
 | 
				
			||||||
 | 
					     * @returns DealAddServiceResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static addDealService({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealAddServiceRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealAddServiceResponse> {
 | 
				
			||||||
        return __request(OpenAPI, {
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
            method: 'POST',
 | 
					            method: 'POST',
 | 
				
			||||||
            url: '/deal/services/add',
 | 
					            url: '/deal/services/add',
 | 
				
			||||||
@@ -105,4 +135,96 @@ export class DealService {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Services Update
 | 
				
			||||||
 | 
					     * @returns DealUpdateServiceQuantityResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static updateDealServiceQuantity({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealUpdateServiceQuantityRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealUpdateServiceQuantityResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/services/update-quantity',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Services Delete
 | 
				
			||||||
 | 
					     * @returns DealDeleteServiceResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static deleteDealService({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealDeleteServiceRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealDeleteServiceResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/services/delete',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Services Delete
 | 
				
			||||||
 | 
					     * @returns DealDeleteServicesResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static deleteMultipleDealServices({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealDeleteServicesRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealDeleteServicesResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/services/delete/multiple',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 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`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,11 @@ import {
 | 
				
			|||||||
    useMantineReactTable
 | 
					    useMantineReactTable
 | 
				
			||||||
} from "mantine-react-table";
 | 
					} from "mantine-react-table";
 | 
				
			||||||
import {MRT_Localization_RU} from "mantine-react-table/locales/ru/index.cjs";
 | 
					import {MRT_Localization_RU} from "mantine-react-table/locales/ru/index.cjs";
 | 
				
			||||||
import {forwardRef, useImperativeHandle} from 'react';
 | 
					import {forwardRef, useEffect, useImperativeHandle} from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props<T extends Record<string, any>, K extends keyof T> = {
 | 
					type Props<T extends Record<string, any>, K extends keyof T> = {
 | 
				
			||||||
    data: T[],
 | 
					    data: T[],
 | 
				
			||||||
 | 
					    onSelectionChange?: (selectedRows: T[]) => void,
 | 
				
			||||||
    columns: MRT_ColumnDef<T>[],
 | 
					    columns: MRT_ColumnDef<T>[],
 | 
				
			||||||
    restProps?: MRT_TableOptions<T>,
 | 
					    restProps?: MRT_TableOptions<T>,
 | 
				
			||||||
    striped?: boolean
 | 
					    striped?: boolean
 | 
				
			||||||
@@ -23,7 +24,7 @@ export type BaseTableRef<T extends MRT_RowData> = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const BaseTable = forwardRef<BaseTableRef<any>, Props<any>>((props, ref) => {
 | 
					export const BaseTable = forwardRef<BaseTableRef<any>, Props<any>>((props, ref) => {
 | 
				
			||||||
    const {data, columns, restProps, striped} = props;
 | 
					    const {data, columns, restProps, striped, onSelectionChange} = props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const table = useMantineReactTable({
 | 
					    const table = useMantineReactTable({
 | 
				
			||||||
        localization: MRT_Localization_RU,
 | 
					        localization: MRT_Localization_RU,
 | 
				
			||||||
@@ -34,8 +35,14 @@ export const BaseTable = forwardRef<BaseTableRef<any>, Props<any>>((props, ref)
 | 
				
			|||||||
            striped: striped
 | 
					            striped: striped
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        enableTopToolbar: false,
 | 
					        enableTopToolbar: false,
 | 
				
			||||||
 | 
					        enableBottomToolbar: false,
 | 
				
			||||||
 | 
					        enableRowSelection: onSelectionChange !== undefined,
 | 
				
			||||||
        ...restProps,
 | 
					        ...restProps,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (!onSelectionChange) return;
 | 
				
			||||||
 | 
					        onSelectionChange(table.getSelectedRowModel().rows.map(row => row.original))
 | 
				
			||||||
 | 
					    }, [table.getState().rowSelection]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Используем useImperativeHandle для определения, что будет доступно через ref
 | 
					    // Используем useImperativeHandle для определения, что будет доступно через ref
 | 
				
			||||||
    useImperativeHandle(ref, () => ({
 | 
					    useImperativeHandle(ref, () => ({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,25 @@
 | 
				
			|||||||
import {FC} from "react";
 | 
					import {FC} from "react";
 | 
				
			||||||
import {DealSummary} from "../../../client";
 | 
					import {DealService, DealSummary} from "../../../client";
 | 
				
			||||||
import styles from './DealSummaryCard.module.css';
 | 
					import styles from './DealSummaryCard.module.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {Text} from '@mantine/core';
 | 
					import {Text} from '@mantine/core';
 | 
				
			||||||
import classNames from "classnames";
 | 
					import classNames from "classnames";
 | 
				
			||||||
 | 
					import {useDealPageContext} from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
    dealSummary: DealSummary
 | 
					    dealSummary: DealSummary
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DealSummaryCard: FC<Props> = ({dealSummary}) => {
 | 
					const DealSummaryCard: FC<Props> = ({dealSummary}) => {
 | 
				
			||||||
 | 
					    const {setSelectedDeal} = useDealPageContext();
 | 
				
			||||||
 | 
					    const onDealSummaryClick = () => {
 | 
				
			||||||
 | 
					        DealService.getDealById({dealId: dealSummary.id})
 | 
				
			||||||
 | 
					            .then((deal) => {
 | 
				
			||||||
 | 
					                setSelectedDeal(deal);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div className={styles['container']}>
 | 
					        <div onClick={() => onDealSummaryClick()} className={styles['container']}>
 | 
				
			||||||
            <div className={styles['flex-row']}>
 | 
					            <div className={styles['flex-row']}>
 | 
				
			||||||
                <div className={styles['flex-item']}>
 | 
					                <div className={styles['flex-item']}>
 | 
				
			||||||
                    <Text size={"sm"} c={"gray.6"}>
 | 
					                    <Text size={"sm"} c={"gray.6"}>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								src/components/PlusMinusInput/PlusMinusInput.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/PlusMinusInput/PlusMinusInput.module.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.number-input {
 | 
				
			||||||
 | 
					    width: rem(50);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										97
									
								
								src/components/PlusMinusInput/PlusMinusInput.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/components/PlusMinusInput/PlusMinusInput.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					import {ActionIcon, Flex, NumberInput, rem} from "@mantine/core";
 | 
				
			||||||
 | 
					import {IconMinus, IconPlus} from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import styles from './PlusMinusInput.module.css';
 | 
				
			||||||
 | 
					import {FC, useEffect, useState} from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ControlledValueProps = {
 | 
				
			||||||
 | 
					    value: number;
 | 
				
			||||||
 | 
					    onChange: (value: number) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RestProps = {
 | 
				
			||||||
 | 
					    defaultValue?: number;
 | 
				
			||||||
 | 
					    onChange: (value: number) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = RestProps & Partial<ControlledValueProps>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PlusMinusInput: FC<Props> = (props: Props) => {
 | 
				
			||||||
 | 
					    const isControlled = props.value !== undefined;
 | 
				
			||||||
 | 
					    const [internalValue, setInternalValue] = useState(props.defaultValue || 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const value = isControlled ? props.value : internalValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onMinusClick = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const newValue = (value || 0) - 1;
 | 
				
			||||||
 | 
					        if (newValue < 0) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(newValue);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            setInternalValue(newValue);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onPlusClick = () => {
 | 
				
			||||||
 | 
					        const newValue = (value || 0) + 1;
 | 
				
			||||||
 | 
					        if (isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(newValue);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            setInternalValue(newValue);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleInputChange = (event: number | string) => {
 | 
				
			||||||
 | 
					        let newValue = typeof event === "string" ? 0 : event;
 | 
				
			||||||
 | 
					        if (isNaN(newValue) || newValue < 0) {
 | 
				
			||||||
 | 
					            newValue = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(newValue);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            setInternalValue(newValue);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (!isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(internalValue);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, [internalValue]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Flex
 | 
				
			||||||
 | 
					            align={"center"}
 | 
				
			||||||
 | 
					            gap={rem(10)}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <ActionIcon
 | 
				
			||||||
 | 
					                disabled={value === 0}
 | 
				
			||||||
 | 
					                onClick={onMinusClick}
 | 
				
			||||||
 | 
					                variant={"default"}>
 | 
				
			||||||
 | 
					                <IconMinus/>
 | 
				
			||||||
 | 
					            </ActionIcon>
 | 
				
			||||||
 | 
					            <NumberInput
 | 
				
			||||||
 | 
					                min={0}
 | 
				
			||||||
 | 
					                styles={{
 | 
				
			||||||
 | 
					                    input: {
 | 
				
			||||||
 | 
					                        textAlign: "center"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                allowNegative={false}
 | 
				
			||||||
 | 
					                hideControls
 | 
				
			||||||
 | 
					                value={value}
 | 
				
			||||||
 | 
					                className={styles['number-input']}
 | 
				
			||||||
 | 
					                onChange={(event) => handleInputChange(event)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <ActionIcon
 | 
				
			||||||
 | 
					                onClick={onPlusClick}
 | 
				
			||||||
 | 
					                variant={"default"}>
 | 
				
			||||||
 | 
					                <IconPlus/>
 | 
				
			||||||
 | 
					            </ActionIcon>
 | 
				
			||||||
 | 
					        </Flex>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default PlusMinusInput;
 | 
				
			||||||
							
								
								
									
										63
									
								
								src/components/ServiceSelect/ServiceSelect.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/components/ServiceSelect/ServiceSelect.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					import {ServiceSchema} from "../../client";
 | 
				
			||||||
 | 
					import {FC, useEffect, useMemo, useState} from "react";
 | 
				
			||||||
 | 
					import {Select, SelectProps} from "@mantine/core";
 | 
				
			||||||
 | 
					import useServicesList from "../../pages/ServicesPage/hooks/useServicesList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ControlledValueProps = {
 | 
				
			||||||
 | 
					    value: ServiceSchema;
 | 
				
			||||||
 | 
					    onChange: (value: ServiceSchema) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type RestProps = {
 | 
				
			||||||
 | 
					    defaultValue?: ServiceSchema;
 | 
				
			||||||
 | 
					    onChange: (value: ServiceSchema) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Props = (RestProps & Partial<ControlledValueProps>) & Omit<SelectProps, 'value' | 'onChange'>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ServiceSelect: FC<Props> = (props) => {
 | 
				
			||||||
 | 
					    const isControlled = props.value !== undefined;
 | 
				
			||||||
 | 
					    const [internalValue, setInternalValue] = useState<ServiceSchema | undefined>(props.defaultValue);
 | 
				
			||||||
 | 
					    const value = isControlled ? props.value : internalValue;
 | 
				
			||||||
 | 
					    const {services} = useServicesList();
 | 
				
			||||||
 | 
					    const categories = useMemo(() => services.reduce((acc, service) => {
 | 
				
			||||||
 | 
					        if (!acc.includes(service.category.name)) {
 | 
				
			||||||
 | 
					            acc.push(service.category.name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return acc;
 | 
				
			||||||
 | 
					    }, [] as string[]), [services]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const data = useMemo(() => categories.map(category => ({
 | 
				
			||||||
 | 
					        group: category,
 | 
				
			||||||
 | 
					        items: services.filter(service => service.category.name === category)
 | 
				
			||||||
 | 
					            .map(service => ({
 | 
				
			||||||
 | 
					                value: service.id.toString(),
 | 
				
			||||||
 | 
					                label: service.name
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					    })), [services, categories]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleOnChange = (value: string) => {
 | 
				
			||||||
 | 
					        if (isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(services.find(service => service.id.toString() === value) as ServiceSchema);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setInternalValue(services.find(service => service.id.toString() === value) as ServiceSchema);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (!isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(internalValue as ServiceSchema);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, [internalValue]);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Select
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					            value={value?.id.toString()}
 | 
				
			||||||
 | 
					            withCheckIcon={false}
 | 
				
			||||||
 | 
					            searchable
 | 
				
			||||||
 | 
					            onChange={event => event && handleOnChange(event)}
 | 
				
			||||||
 | 
					            data={data}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ServiceSelect;
 | 
				
			||||||
@@ -3,6 +3,7 @@ import CreateServiceCategoryModal from "../pages/ServicesPage/modals/CreateServi
 | 
				
			|||||||
import CreateServiceModal from "../pages/ServicesPage/modals/CreateServiceModal.tsx";
 | 
					import CreateServiceModal from "../pages/ServicesPage/modals/CreateServiceModal.tsx";
 | 
				
			||||||
import createProductModal from "../pages/ProductsPage/modals/CreateProductModal/CreateProductModal.tsx";
 | 
					import createProductModal from "../pages/ProductsPage/modals/CreateProductModal/CreateProductModal.tsx";
 | 
				
			||||||
import ProductFormModal from "../pages/ClientsPage/modals/ClientFormModal/ClientFormModal.tsx";
 | 
					import ProductFormModal from "../pages/ClientsPage/modals/ClientFormModal/ClientFormModal.tsx";
 | 
				
			||||||
 | 
					import AddDealServiceModal from "../pages/LeadsPage/modals/AddDealServiceModal.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const modals = {
 | 
					export const modals = {
 | 
				
			||||||
    enterDeadline: EnterDeadlineModal,
 | 
					    enterDeadline: EnterDeadlineModal,
 | 
				
			||||||
@@ -10,4 +11,5 @@ export const modals = {
 | 
				
			|||||||
    createService: CreateServiceModal,
 | 
					    createService: CreateServiceModal,
 | 
				
			||||||
    createProduct: createProductModal,
 | 
					    createProduct: createProductModal,
 | 
				
			||||||
    productFormModal: ProductFormModal,
 | 
					    productFormModal: ProductFormModal,
 | 
				
			||||||
 | 
					    addDealService: AddDealServiceModal
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import {FC} from "react";
 | 
					import {FC, useState} from "react";
 | 
				
			||||||
import ClientsTable from "./components/ClientsTable/ClientsTable.tsx";
 | 
					import ClientsTable from "./components/ClientsTable/ClientsTable.tsx";
 | 
				
			||||||
import useClientsList from "./hooks/useClientsList.tsx";
 | 
					import useClientsList from "./hooks/useClientsList.tsx";
 | 
				
			||||||
import PageBlock from "../../components/PageBlock/PageBlock.tsx";
 | 
					import PageBlock from "../../components/PageBlock/PageBlock.tsx";
 | 
				
			||||||
@@ -7,6 +7,7 @@ import {Button} from "@mantine/core";
 | 
				
			|||||||
import {modals} from "@mantine/modals";
 | 
					import {modals} from "@mantine/modals";
 | 
				
			||||||
import {ClientSchema, ClientService} from "../../client";
 | 
					import {ClientSchema, ClientService} from "../../client";
 | 
				
			||||||
import {notifications} from "../../shared/lib/notifications.ts";
 | 
					import {notifications} from "../../shared/lib/notifications.ts";
 | 
				
			||||||
 | 
					import PlusMinusInput from "../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ClientsPage: FC = () => {
 | 
					const ClientsPage: FC = () => {
 | 
				
			||||||
    const {clients, refetch} = useClientsList();
 | 
					    const {clients, refetch} = useClientsList();
 | 
				
			||||||
@@ -58,6 +59,8 @@ const ClientsPage: FC = () => {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [a, setA] = useState(5);
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div className={styles['container']}>
 | 
					        <div className={styles['container']}>
 | 
				
			||||||
            <PageBlock>
 | 
					            <PageBlock>
 | 
				
			||||||
@@ -68,7 +71,14 @@ const ClientsPage: FC = () => {
 | 
				
			|||||||
                    >
 | 
					                    >
 | 
				
			||||||
                        Создать клиента
 | 
					                        Создать клиента
 | 
				
			||||||
                    </Button>
 | 
					                    </Button>
 | 
				
			||||||
 | 
					                    <PlusMinusInput onChange={event=>{
 | 
				
			||||||
 | 
					                        console.log(event);
 | 
				
			||||||
 | 
					                        setA(event)
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                                    value={a}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            </PageBlock>
 | 
					            </PageBlock>
 | 
				
			||||||
            <PageBlock>
 | 
					            <PageBlock>
 | 
				
			||||||
                <ClientsTable
 | 
					                <ClientsTable
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,8 @@ const BaseFormModal = <T, >(props: Props<T>) => {
 | 
				
			|||||||
    const isEditing = 'onChange' in props;
 | 
					    const isEditing = 'onChange' in props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onSubmit = (values: T) => {
 | 
					    const onSubmit = (values: T) => {
 | 
				
			||||||
 | 
					        console.log('----values');
 | 
				
			||||||
 | 
					        console.log(values)
 | 
				
			||||||
        if (isEditing) {
 | 
					        if (isEditing) {
 | 
				
			||||||
            props.onChange(values);
 | 
					            props.onChange(values);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import {useDealServicesTableColumns} from "./columns.tsx";
 | 
				
			||||||
 | 
					import {BaseTable} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					import {DealServiceSchema} from "../../../../client";
 | 
				
			||||||
 | 
					import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
 | 
				
			||||||
 | 
					import {MRT_TableOptions} from "mantine-react-table";
 | 
				
			||||||
 | 
					import {ActionIcon, Box, Button, Flex, rem, Tooltip} from "@mantine/core";
 | 
				
			||||||
 | 
					import {openContextModal} from "@mantine/modals";
 | 
				
			||||||
 | 
					import {IconTrash} from "@tabler/icons-react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RestProps = {
 | 
				
			||||||
 | 
					    onMultipleDelete?: (items: DealServiceSchema[]) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Props = CRUDTableProps<DealServiceSchema> & RestProps;
 | 
				
			||||||
 | 
					const DealServicesTable: FC<Props> = (
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        items,
 | 
				
			||||||
 | 
					        onChange,
 | 
				
			||||||
 | 
					        onDelete,
 | 
				
			||||||
 | 
					        onCreate,
 | 
				
			||||||
 | 
					        onSelectionChange,
 | 
				
			||||||
 | 
					        onMultipleDelete,
 | 
				
			||||||
 | 
					        tableRef
 | 
				
			||||||
 | 
					    }) => {
 | 
				
			||||||
 | 
					    const onQuantityChange = (service: DealServiceSchema, quantity: number) => {
 | 
				
			||||||
 | 
					        if (!onChange) return;
 | 
				
			||||||
 | 
					        if (quantity <= 0 && onDelete) {
 | 
				
			||||||
 | 
					            onDelete(service);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        onChange({...service, quantity});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const columns = useDealServicesTableColumns({
 | 
				
			||||||
 | 
					        onChange: onQuantityChange,
 | 
				
			||||||
 | 
					        data: items
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const onCreateClick = () => {
 | 
				
			||||||
 | 
					        if (!onCreate) return;
 | 
				
			||||||
 | 
					        openContextModal({
 | 
				
			||||||
 | 
					            title: "Добавление услуги",
 | 
				
			||||||
 | 
					            modal: "addDealService",
 | 
				
			||||||
 | 
					            innerProps: {
 | 
				
			||||||
 | 
					                onCreate: (event) => onCreate(event as DealServiceSchema)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseTable
 | 
				
			||||||
 | 
					            ref={tableRef}
 | 
				
			||||||
 | 
					            data={items}
 | 
				
			||||||
 | 
					            columns={columns}
 | 
				
			||||||
 | 
					            onSelectionChange={onSelectionChange}
 | 
				
			||||||
 | 
					            restProps={{
 | 
				
			||||||
 | 
					                enableGrouping: true,
 | 
				
			||||||
 | 
					                initialState: {grouping: ["service.category"]},
 | 
				
			||||||
 | 
					                enableColumnActions: false,
 | 
				
			||||||
 | 
					                enableSorting: false,
 | 
				
			||||||
 | 
					                enableBottomToolbar: true,
 | 
				
			||||||
 | 
					                enableRowActions: true,
 | 
				
			||||||
 | 
					                enableRowSelection: true,
 | 
				
			||||||
 | 
					                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>
 | 
				
			||||||
 | 
					                        )}
 | 
				
			||||||
 | 
					                        <Button onClick={onCreateClick} variant={"default"}>
 | 
				
			||||||
 | 
					                            Добавить услугу
 | 
				
			||||||
 | 
					                        </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    </Flex>
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                renderRowActions: ({row}) => (
 | 
				
			||||||
 | 
					                    <Flex gap="md">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <Tooltip label="Удалить">
 | 
				
			||||||
 | 
					                            <ActionIcon onClick={() => {
 | 
				
			||||||
 | 
					                                if (onDelete) onDelete(row.original);
 | 
				
			||||||
 | 
					                            }} variant={"default"}>
 | 
				
			||||||
 | 
					                                <IconTrash/>
 | 
				
			||||||
 | 
					                            </ActionIcon>
 | 
				
			||||||
 | 
					                        </Tooltip>
 | 
				
			||||||
 | 
					                    </Flex>
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            } as MRT_TableOptions<DealServiceSchema>}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DealServicesTable;
 | 
				
			||||||
							
								
								
									
										66
									
								
								src/pages/LeadsPage/components/DealServicesTable/columns.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/pages/LeadsPage/components/DealServicesTable/columns.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					import {MRT_ColumnDef} from "mantine-react-table";
 | 
				
			||||||
 | 
					import {useMemo} from "react";
 | 
				
			||||||
 | 
					import {DealServiceSchema} from "../../../../client";
 | 
				
			||||||
 | 
					import PlusMinusInput from "../../../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    onChange: (service: DealServiceSchema, quantity: number) => void;
 | 
				
			||||||
 | 
					    data: DealServiceSchema[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useDealServicesTableColumns = (props: Props) => {
 | 
				
			||||||
 | 
					    const {onChange, data} = props;
 | 
				
			||||||
 | 
					    const totalPrice = useMemo(() =>
 | 
				
			||||||
 | 
					            data.reduce((acc, row) => acc + row.quantity * row.service.price, 0)
 | 
				
			||||||
 | 
					        ,
 | 
				
			||||||
 | 
					        [data]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return useMemo<MRT_ColumnDef<DealServiceSchema>[]>(() => [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            accessorKey: "service.category",
 | 
				
			||||||
 | 
					            header: "Категория",
 | 
				
			||||||
 | 
					            accessorFn: (row) => row.service.category.name,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            accessorKey: "service.name",
 | 
				
			||||||
 | 
					            header: "Услуга",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            accessorKey: "service.price",
 | 
				
			||||||
 | 
					            header: "Цена",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            accessorKey: "quantity",
 | 
				
			||||||
 | 
					            header: "Количество",
 | 
				
			||||||
 | 
					            Cell: ({row}) => {
 | 
				
			||||||
 | 
					                return (
 | 
				
			||||||
 | 
					                    <PlusMinusInput
 | 
				
			||||||
 | 
					                        value={row.original.quantity}
 | 
				
			||||||
 | 
					                        onChange={(value) => onChange(row.original, value)}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            header: "Сумма",
 | 
				
			||||||
 | 
					            Cell: ({row}) => {
 | 
				
			||||||
 | 
					                return row.original.quantity * row.original.service.price;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            aggregationFn: "sum",
 | 
				
			||||||
 | 
					            AggregatedCell: ({cell}) => {
 | 
				
			||||||
 | 
					                return <>Итоговая сумма по категории: {" "}
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        cell.row.subRows?.reduce((acc, row) =>
 | 
				
			||||||
 | 
					                            acc + row.original.quantity * row.original.service.price, 0)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                </>;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            Footer: <>Итоговая сумма по услугам: {totalPrice}</>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ], [onChange]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								src/pages/LeadsPage/contexts/DealPageContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/pages/LeadsPage/contexts/DealPageContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import {createContext, FC, useContext, useState} from "react";
 | 
				
			||||||
 | 
					import {DealSchema} from "../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DealPageContextState = {
 | 
				
			||||||
 | 
					    selectedDeal?: DealSchema;
 | 
				
			||||||
 | 
					    setSelectedDeal: (deal: DealSchema | undefined) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealPageContext = createContext<DealPageContextState | undefined>(undefined);
 | 
				
			||||||
 | 
					const useDealPageContextState = () => {
 | 
				
			||||||
 | 
					    const [selectedDeal, setSelectedDeal] = useState<DealSchema | undefined>(undefined);
 | 
				
			||||||
 | 
					    return {selectedDeal, setSelectedDeal};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DealPageContextProviderProps = {
 | 
				
			||||||
 | 
					    children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DealPageContextProvider: FC<DealPageContextProviderProps> = ({children}) => {
 | 
				
			||||||
 | 
					    const state = useDealPageContextState();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <DealPageContext.Provider value={state}>
 | 
				
			||||||
 | 
					            {children}
 | 
				
			||||||
 | 
					        </DealPageContext.Provider>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useDealPageContext = () => {
 | 
				
			||||||
 | 
					    const context = useContext(DealPageContext);
 | 
				
			||||||
 | 
					    if (!context) {
 | 
				
			||||||
 | 
					        throw new Error('useDealPageContext must be used within a DealPageContextProvider');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return context;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										175
									
								
								src/pages/LeadsPage/drawers/DealEditDrawer/DealEditDrawer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								src/pages/LeadsPage/drawers/DealEditDrawer/DealEditDrawer.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					import {Drawer, 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 {notifications} from "../../../../shared/lib/notifications.ts";
 | 
				
			||||||
 | 
					import {modals} from "@mantine/modals";
 | 
				
			||||||
 | 
					import {BaseTableRef} from "../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useDealServicesTableState = () => {
 | 
				
			||||||
 | 
					    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
				
			||||||
 | 
					    const tableRef = useRef<BaseTableRef<DealServiceSchema>>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onServiceUpdate = (service: DealServiceSchema) => {
 | 
				
			||||||
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
 | 
					        DealService.updateDealServiceQuantity({
 | 
				
			||||||
 | 
					            requestBody: {
 | 
				
			||||||
 | 
					                dealId: selectedDeal.id,
 | 
				
			||||||
 | 
					                serviceId: service.service.id,
 | 
				
			||||||
 | 
					                quantity: service.quantity
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }).then(async ({ok, message}) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!ok) {
 | 
				
			||||||
 | 
					                notifications.guess(ok, {message});
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            await DealService.getDealById({dealId: selectedDeal.id})
 | 
				
			||||||
 | 
					                .then(setSelectedDeal)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onServiceDelete = (service: DealServiceSchema) => {
 | 
				
			||||||
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
 | 
					        modals.openConfirmModal({
 | 
				
			||||||
 | 
					            title: "Удаление услуги",
 | 
				
			||||||
 | 
					            children: (
 | 
				
			||||||
 | 
					                <>
 | 
				
			||||||
 | 
					                    <Text>
 | 
				
			||||||
 | 
					                        Вы уверены, что хотите удалить услугу:
 | 
				
			||||||
 | 
					                    </Text>
 | 
				
			||||||
 | 
					                    <Text>
 | 
				
			||||||
 | 
					                        {service.service.name}?
 | 
				
			||||||
 | 
					                    </Text>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                </>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            onConfirm: () => {
 | 
				
			||||||
 | 
					                DealService.deleteDealService({
 | 
				
			||||||
 | 
					                    requestBody: {
 | 
				
			||||||
 | 
					                        dealId: selectedDeal.id,
 | 
				
			||||||
 | 
					                        serviceId: service.service.id
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }).then(async ({ok, message}) => {
 | 
				
			||||||
 | 
					                    if (!ok) {
 | 
				
			||||||
 | 
					                        notifications.guess(ok, {message});
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    await DealService.getDealById({dealId: selectedDeal.id})
 | 
				
			||||||
 | 
					                        .then(setSelectedDeal)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            labels: {
 | 
				
			||||||
 | 
					                cancel: "Отмена",
 | 
				
			||||||
 | 
					                confirm: "Удалить"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onServiceCreate = (service: DealServiceSchema) => {
 | 
				
			||||||
 | 
					        console.log('-------Drawer')
 | 
				
			||||||
 | 
					        console.log(service);
 | 
				
			||||||
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
 | 
					        DealService.addDealService({
 | 
				
			||||||
 | 
					            requestBody: {
 | 
				
			||||||
 | 
					                dealId: selectedDeal.id,
 | 
				
			||||||
 | 
					                serviceId: service.service.id,
 | 
				
			||||||
 | 
					                quantity: service.quantity
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }).then(async ({ok, message}) => {
 | 
				
			||||||
 | 
					            if (!ok) {
 | 
				
			||||||
 | 
					                notifications.guess(ok, {message});
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            await DealService.getDealById({dealId: selectedDeal.id})
 | 
				
			||||||
 | 
					                .then(setSelectedDeal)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onsServiceMultipleDelete = (items: DealServiceSchema[]) => {
 | 
				
			||||||
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
 | 
					        modals.openConfirmModal({
 | 
				
			||||||
 | 
					            title: "Удаление услуг",
 | 
				
			||||||
 | 
					            children: (
 | 
				
			||||||
 | 
					                <>
 | 
				
			||||||
 | 
					                    <Text>
 | 
				
			||||||
 | 
					                        Вы уверены, что хотите удалить выбранные услуги?
 | 
				
			||||||
 | 
					                    </Text>
 | 
				
			||||||
 | 
					                </>
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            onConfirm: () => {
 | 
				
			||||||
 | 
					                DealService.deleteMultipleDealServices({
 | 
				
			||||||
 | 
					                    requestBody: {
 | 
				
			||||||
 | 
					                        dealId: selectedDeal.id,
 | 
				
			||||||
 | 
					                        serviceIds: items.map(item => item.service.id)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }).then(async ({ok, message}) => {
 | 
				
			||||||
 | 
					                    if (!ok) {
 | 
				
			||||||
 | 
					                        notifications.guess(ok, {message});
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    await DealService.getDealById({dealId: selectedDeal.id})
 | 
				
			||||||
 | 
					                        .then(setSelectedDeal)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            labels: {
 | 
				
			||||||
 | 
					                cancel: "Отмена",
 | 
				
			||||||
 | 
					                confirm: "Удалить"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        onServiceUpdate,
 | 
				
			||||||
 | 
					        onServiceDelete,
 | 
				
			||||||
 | 
					        onServiceCreate,
 | 
				
			||||||
 | 
					        onsServiceMultipleDelete,
 | 
				
			||||||
 | 
					        tableRef,
 | 
				
			||||||
 | 
					        services: selectedDeal?.services || []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealEditDrawerServicesTable = () => {
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					        services,
 | 
				
			||||||
 | 
					        tableRef,
 | 
				
			||||||
 | 
					        onServiceCreate,
 | 
				
			||||||
 | 
					        onServiceUpdate,
 | 
				
			||||||
 | 
					        onServiceDelete,
 | 
				
			||||||
 | 
					        onsServiceMultipleDelete
 | 
				
			||||||
 | 
					    } = useDealServicesTableState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (<DealServicesTable
 | 
				
			||||||
 | 
					        tableRef={tableRef}
 | 
				
			||||||
 | 
					        items={services}
 | 
				
			||||||
 | 
					        onChange={onServiceUpdate}
 | 
				
			||||||
 | 
					        onDelete={onServiceDelete}
 | 
				
			||||||
 | 
					        onCreate={onServiceCreate}
 | 
				
			||||||
 | 
					        onMultipleDelete={onsServiceMultipleDelete}
 | 
				
			||||||
 | 
					    />)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const useDealEditDrawerState = () => {
 | 
				
			||||||
 | 
					    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        isVisible: selectedDeal !== undefined,
 | 
				
			||||||
 | 
					        onClose: () => setSelectedDeal(undefined)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DealEditDrawer: FC = () => {
 | 
				
			||||||
 | 
					    const {isVisible, onClose} = useDealEditDrawerState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Drawer
 | 
				
			||||||
 | 
					            size={"95%"}
 | 
				
			||||||
 | 
					            position={"right"}
 | 
				
			||||||
 | 
					            onClose={onClose}
 | 
				
			||||||
 | 
					            opened={isVisible}>
 | 
				
			||||||
 | 
					            <DealEditDrawerServicesTable/>
 | 
				
			||||||
 | 
					        </Drawer>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DealEditDrawer;
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/pages/LeadsPage/modals/AddDealServiceModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/pages/LeadsPage/modals/AddDealServiceModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					import {ContextModalProps} from "@mantine/modals";
 | 
				
			||||||
 | 
					import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
 | 
				
			||||||
 | 
					import {DealServiceSchema} from "../../../client";
 | 
				
			||||||
 | 
					import {useForm} from "@mantine/form";
 | 
				
			||||||
 | 
					import {NumberInput} from "@mantine/core";
 | 
				
			||||||
 | 
					import ServiceSelect from "../../../components/ServiceSelect/ServiceSelect.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = CreateEditFormProps<Partial<DealServiceSchema>>;
 | 
				
			||||||
 | 
					const AddDealServiceModal = ({
 | 
				
			||||||
 | 
					                                 context,
 | 
				
			||||||
 | 
					                                 id,
 | 
				
			||||||
 | 
					                                 innerProps
 | 
				
			||||||
 | 
					                             }: ContextModalProps<Props>) => {
 | 
				
			||||||
 | 
					    const form = useForm<Partial<DealServiceSchema>>({
 | 
				
			||||||
 | 
					        initialValues: {
 | 
				
			||||||
 | 
					            service: undefined,
 | 
				
			||||||
 | 
					            quantity: 0,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        validate: {
 | 
				
			||||||
 | 
					            service: (service?: DealServiceSchema['service']) => service !== undefined ? null : "Необходимо выбрать услугу",
 | 
				
			||||||
 | 
					            quantity: (quantity?: number) => (quantity && quantity > 0) ? null : "Количество должно быть больше 0"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const onClose = () => {
 | 
				
			||||||
 | 
					        context.closeContextModal(id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseFormModal
 | 
				
			||||||
 | 
					            {...innerProps}
 | 
				
			||||||
 | 
					            form={form}
 | 
				
			||||||
 | 
					            closeOnSubmit
 | 
				
			||||||
 | 
					            onClose={onClose}>
 | 
				
			||||||
 | 
					            <BaseFormModal.Body>
 | 
				
			||||||
 | 
					                <>
 | 
				
			||||||
 | 
					                    <ServiceSelect
 | 
				
			||||||
 | 
					                        placeholder={"Выберите услугу"}
 | 
				
			||||||
 | 
					                        label={"Услуга"}
 | 
				
			||||||
 | 
					                        {...form.getInputProps('service')}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    <NumberInput
 | 
				
			||||||
 | 
					                        placeholder={"Введите количество"}
 | 
				
			||||||
 | 
					                        label={"Количество"}
 | 
				
			||||||
 | 
					                        min={1}
 | 
				
			||||||
 | 
					                        {...form.getInputProps('quantity')}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                </>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            </BaseFormModal.Body>
 | 
				
			||||||
 | 
					        </BaseFormModal>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AddDealServiceModal;
 | 
				
			||||||
@@ -5,6 +5,8 @@ import {DragDropContext} from "@hello-pangea/dnd";
 | 
				
			|||||||
import {useDealSummaries} from "../hooks/useDealSummaries.tsx";
 | 
					import {useDealSummaries} from "../hooks/useDealSummaries.tsx";
 | 
				
			||||||
import {DealStatus} from "../../../shared/enums/DealStatus.ts";
 | 
					import {DealStatus} from "../../../shared/enums/DealStatus.ts";
 | 
				
			||||||
import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
 | 
					import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
 | 
				
			||||||
 | 
					import DealEditDrawer from "../drawers/DealEditDrawer/DealEditDrawer.tsx";
 | 
				
			||||||
 | 
					import {DealPageContextProvider} from "../contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const LeadsPage: FC = () => {
 | 
					export const LeadsPage: FC = () => {
 | 
				
			||||||
@@ -25,45 +27,50 @@ export const LeadsPage: FC = () => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
            <PageBlock>
 | 
					            <DealPageContextProvider>
 | 
				
			||||||
                <div className={styles['container']}>
 | 
					
 | 
				
			||||||
                    <div className={styles['boards']}>
 | 
					                <PageBlock>
 | 
				
			||||||
                        <DragDropContext onDragEnd={onDragEnd}>
 | 
					                    <div className={styles['container']}>
 | 
				
			||||||
                            <Board
 | 
					                        <div className={styles['boards']}>
 | 
				
			||||||
                                withCreateButton
 | 
					                            <DragDropContext onDragEnd={onDragEnd}>
 | 
				
			||||||
                                summaries={summaries
 | 
					                                <Board
 | 
				
			||||||
                                    .filter(summary => summary.status == DealStatus.AWAITING_ACCEPTANCE)}
 | 
					                                    withCreateButton
 | 
				
			||||||
                                title={"Ожидает приемки"}
 | 
					                                    summaries={summaries
 | 
				
			||||||
                                droppableId={"AWAITING_ACCEPTANCE"}
 | 
					                                        .filter(summary => summary.status == DealStatus.AWAITING_ACCEPTANCE)}
 | 
				
			||||||
                            />
 | 
					                                    title={"Ожидает приемки"}
 | 
				
			||||||
                            <Board
 | 
					                                    droppableId={"AWAITING_ACCEPTANCE"}
 | 
				
			||||||
                                summaries={summaries
 | 
					                                />
 | 
				
			||||||
                                    .filter(summary => summary.status == DealStatus.PACKAGING)}
 | 
					                                <Board
 | 
				
			||||||
                                title={"Упаковка"}
 | 
					                                    summaries={summaries
 | 
				
			||||||
                                droppableId={"PACKAGING"}
 | 
					                                        .filter(summary => summary.status == DealStatus.PACKAGING)}
 | 
				
			||||||
                            />
 | 
					                                    title={"Упаковка"}
 | 
				
			||||||
                            <Board
 | 
					                                    droppableId={"PACKAGING"}
 | 
				
			||||||
                                summaries={summaries
 | 
					                                />
 | 
				
			||||||
                                    .filter(summary => summary.status == DealStatus.AWAITING_SHIPMENT)}
 | 
					                                <Board
 | 
				
			||||||
                                title={"Ожидает отгрузки"}
 | 
					                                    summaries={summaries
 | 
				
			||||||
                                droppableId={"AWAITING_SHIPMENT"}
 | 
					                                        .filter(summary => summary.status == DealStatus.AWAITING_SHIPMENT)}
 | 
				
			||||||
                            />
 | 
					                                    title={"Ожидает отгрузки"}
 | 
				
			||||||
                            <Board
 | 
					                                    droppableId={"AWAITING_SHIPMENT"}
 | 
				
			||||||
                                summaries={summaries
 | 
					                                />
 | 
				
			||||||
                                    .filter(summary => summary.status == DealStatus.AWAITING_PAYMENT)}
 | 
					                                <Board
 | 
				
			||||||
                                title={"Ожидает оплаты"}
 | 
					                                    summaries={summaries
 | 
				
			||||||
                                droppableId={"AWAITING_PAYMENT"}
 | 
					                                        .filter(summary => summary.status == DealStatus.AWAITING_PAYMENT)}
 | 
				
			||||||
                            />
 | 
					                                    title={"Ожидает оплаты"}
 | 
				
			||||||
                            <Board
 | 
					                                    droppableId={"AWAITING_PAYMENT"}
 | 
				
			||||||
                                summaries={summaries
 | 
					                                />
 | 
				
			||||||
                                    .filter(summary => summary.status == DealStatus.COMPLETED)}
 | 
					                                <Board
 | 
				
			||||||
                                title={"Завершена"}
 | 
					                                    summaries={summaries
 | 
				
			||||||
                                droppableId={"COMPLETED"}
 | 
					                                        .filter(summary => summary.status == DealStatus.COMPLETED)}
 | 
				
			||||||
                            />
 | 
					                                    title={"Завершена"}
 | 
				
			||||||
                        </DragDropContext>
 | 
					                                    droppableId={"COMPLETED"}
 | 
				
			||||||
 | 
					                                />
 | 
				
			||||||
 | 
					                            </DragDropContext>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </PageBlock>
 | 
				
			||||||
            </PageBlock>
 | 
					                <DealEditDrawer
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </DealPageContextProvider>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ type Props = {
 | 
				
			|||||||
    page: number,
 | 
					    page: number,
 | 
				
			||||||
    itemsPerPage: number,
 | 
					    itemsPerPage: number,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const useServicesList = (props: Props) => {
 | 
					const useProductsList = (props: Props) => {
 | 
				
			||||||
    const {clientId, page, itemsPerPage} = props;
 | 
					    const {clientId, page, itemsPerPage} = props;
 | 
				
			||||||
    const {data, refetch} = useQuery({
 | 
					    const {data, refetch} = useQuery({
 | 
				
			||||||
        queryKey: ['getAllServices', clientId, page, itemsPerPage],
 | 
					        queryKey: ['getAllServices', clientId, page, itemsPerPage],
 | 
				
			||||||
@@ -16,4 +16,4 @@ const useServicesList = (props: Props) => {
 | 
				
			|||||||
    const paginationInfo = data?.paginationInfo;
 | 
					    const paginationInfo = data?.paginationInfo;
 | 
				
			||||||
    return {products, paginationInfo, refetch}
 | 
					    return {products, paginationInfo, refetch}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
export default useServicesList;
 | 
					export default useProductsList;
 | 
				
			||||||
@@ -4,11 +4,13 @@ import styles from './ProductsPage.module.css';
 | 
				
			|||||||
import {Button, Text, Pagination} from "@mantine/core";
 | 
					import {Button, Text, Pagination} from "@mantine/core";
 | 
				
			||||||
import ClientSelect from "../../../components/Selects/ClientSelect/ClientSelect.tsx";
 | 
					import ClientSelect from "../../../components/Selects/ClientSelect/ClientSelect.tsx";
 | 
				
			||||||
import ProductsTable from "../components/ProductsTable/ProductsTable.tsx";
 | 
					import ProductsTable from "../components/ProductsTable/ProductsTable.tsx";
 | 
				
			||||||
import useProductsList from "../hooks/useProductsList.tsx";
 | 
					 | 
				
			||||||
import {modals} from "@mantine/modals";
 | 
					import {modals} from "@mantine/modals";
 | 
				
			||||||
import {notifications} from "../../../shared/lib/notifications.ts";
 | 
					import {notifications} from "../../../shared/lib/notifications.ts";
 | 
				
			||||||
import {CreateProductRequest} from "../types.ts";
 | 
					import {CreateProductRequest} from "../types.ts";
 | 
				
			||||||
import {ProductSchema, ProductService} from "../../../client";
 | 
					import {ProductSchema, ProductService} from "../../../client";
 | 
				
			||||||
 | 
					import ServiceSelect from "../../../components/ServiceSelect/ServiceSelect.tsx";
 | 
				
			||||||
 | 
					import useProductsList from "../hooks/useProductsList.tsx";
 | 
				
			||||||
 | 
					import useServicesList from "../../ServicesPage/hooks/useServicesList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ProductsPage: FC = () => {
 | 
					export const ProductsPage: FC = () => {
 | 
				
			||||||
    const [clientId, setClientId] = useState(-1);
 | 
					    const [clientId, setClientId] = useState(-1);
 | 
				
			||||||
@@ -79,8 +81,6 @@ export const ProductsPage: FC = () => {
 | 
				
			|||||||
        if (!paginationInfo) return;
 | 
					        if (!paginationInfo) return;
 | 
				
			||||||
        setTotalPages(paginationInfo.totalPages);
 | 
					        setTotalPages(paginationInfo.totalPages);
 | 
				
			||||||
    }, [paginationInfo]);
 | 
					    }, [paginationInfo]);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
            <div className={styles['container']}>
 | 
					            <div className={styles['container']}>
 | 
				
			||||||
@@ -91,6 +91,9 @@ export const ProductsPage: FC = () => {
 | 
				
			|||||||
                            onClick={() => onCreateProductClick()}
 | 
					                            onClick={() => onCreateProductClick()}
 | 
				
			||||||
                            variant={"default"}
 | 
					                            variant={"default"}
 | 
				
			||||||
                        >Создать</Button>
 | 
					                        >Создать</Button>
 | 
				
			||||||
 | 
					                        {/*<ServiceSelect*/}
 | 
				
			||||||
 | 
					                        {/*    value={selectedService}*/}
 | 
				
			||||||
 | 
					                        {/*    onChange={setSelectedService}/>*/}
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </PageBlock>
 | 
					                </PageBlock>
 | 
				
			||||||
                <PageBlock>
 | 
					                <PageBlock>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,5 +7,6 @@ export interface CRUDTableProps<T extends MRT_RowData> {
 | 
				
			|||||||
    onCreate?: (item: T) => void;
 | 
					    onCreate?: (item: T) => void;
 | 
				
			||||||
    onDelete?: (item: T) => void;
 | 
					    onDelete?: (item: T) => void;
 | 
				
			||||||
    onChange?: (item: T) => void;
 | 
					    onChange?: (item: T) => void;
 | 
				
			||||||
 | 
					    onSelectionChange?: (selectedItems: T[]) => void;
 | 
				
			||||||
    tableRef?: RefObject<BaseTableRef<T>>
 | 
					    tableRef?: RefObject<BaseTableRef<T>>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user