feat: filling deals from excel file
This commit is contained in:
		@@ -30,12 +30,14 @@ export type { BaseShippingWarehouseSchema } from './models/BaseShippingWarehouse
 | 
				
			|||||||
export type { BaseTransactionTagSchema } from './models/BaseTransactionTagSchema';
 | 
					export type { BaseTransactionTagSchema } from './models/BaseTransactionTagSchema';
 | 
				
			||||||
export type { BillPaymentStatus } from './models/BillPaymentStatus';
 | 
					export type { BillPaymentStatus } from './models/BillPaymentStatus';
 | 
				
			||||||
export type { BillStatusUpdateRequest } from './models/BillStatusUpdateRequest';
 | 
					export type { BillStatusUpdateRequest } from './models/BillStatusUpdateRequest';
 | 
				
			||||||
 | 
					export type { Body_parse_deals_excel } from './models/Body_parse_deals_excel';
 | 
				
			||||||
export type { Body_upload_passport_image } from './models/Body_upload_passport_image';
 | 
					export type { Body_upload_passport_image } from './models/Body_upload_passport_image';
 | 
				
			||||||
export type { Body_upload_product_barcode_image } from './models/Body_upload_product_barcode_image';
 | 
					export type { Body_upload_product_barcode_image } from './models/Body_upload_product_barcode_image';
 | 
				
			||||||
export type { Body_upload_product_image } from './models/Body_upload_product_image';
 | 
					export type { Body_upload_product_image } from './models/Body_upload_product_image';
 | 
				
			||||||
export type { BoxSchema } from './models/BoxSchema';
 | 
					export type { BoxSchema } from './models/BoxSchema';
 | 
				
			||||||
export type { CancelDealBillRequest } from './models/CancelDealBillRequest';
 | 
					export type { CancelDealBillRequest } from './models/CancelDealBillRequest';
 | 
				
			||||||
export type { CancelDealBillResponse } from './models/CancelDealBillResponse';
 | 
					export type { CancelDealBillResponse } from './models/CancelDealBillResponse';
 | 
				
			||||||
 | 
					export type { CityBreakdownFromExcelSchema } from './models/CityBreakdownFromExcelSchema';
 | 
				
			||||||
export type { ClientCreateRequest } from './models/ClientCreateRequest';
 | 
					export type { ClientCreateRequest } from './models/ClientCreateRequest';
 | 
				
			||||||
export type { ClientCreateResponse } from './models/ClientCreateResponse';
 | 
					export type { ClientCreateResponse } from './models/ClientCreateResponse';
 | 
				
			||||||
export type { ClientDeleteRequest } from './models/ClientDeleteRequest';
 | 
					export type { ClientDeleteRequest } from './models/ClientDeleteRequest';
 | 
				
			||||||
@@ -52,6 +54,8 @@ export type { CreateBoxInDealSchema } from './models/CreateBoxInDealSchema';
 | 
				
			|||||||
export type { CreateBoxInPalletSchema } from './models/CreateBoxInPalletSchema';
 | 
					export type { CreateBoxInPalletSchema } from './models/CreateBoxInPalletSchema';
 | 
				
			||||||
export type { CreateDealBillRequest } from './models/CreateDealBillRequest';
 | 
					export type { CreateDealBillRequest } from './models/CreateDealBillRequest';
 | 
				
			||||||
export type { CreateDealBillResponse } from './models/CreateDealBillResponse';
 | 
					export type { CreateDealBillResponse } from './models/CreateDealBillResponse';
 | 
				
			||||||
 | 
					export type { CreateDealsFromExcelRequest } from './models/CreateDealsFromExcelRequest';
 | 
				
			||||||
 | 
					export type { CreateDealsFromExcelResponse } from './models/CreateDealsFromExcelResponse';
 | 
				
			||||||
export type { CreateDepartmentRequest } from './models/CreateDepartmentRequest';
 | 
					export type { CreateDepartmentRequest } from './models/CreateDepartmentRequest';
 | 
				
			||||||
export type { CreateDepartmentResponse } from './models/CreateDepartmentResponse';
 | 
					export type { CreateDepartmentResponse } from './models/CreateDepartmentResponse';
 | 
				
			||||||
export type { CreateDepartmentSectionRequest } from './models/CreateDepartmentSectionRequest';
 | 
					export type { CreateDepartmentSectionRequest } from './models/CreateDepartmentSectionRequest';
 | 
				
			||||||
@@ -222,8 +226,12 @@ export type { ManageEmployeeResponse } from './models/ManageEmployeeResponse';
 | 
				
			|||||||
export type { MarketplaceCreateSchema } from './models/MarketplaceCreateSchema';
 | 
					export type { MarketplaceCreateSchema } from './models/MarketplaceCreateSchema';
 | 
				
			||||||
export type { MarketplaceSchema } from './models/MarketplaceSchema';
 | 
					export type { MarketplaceSchema } from './models/MarketplaceSchema';
 | 
				
			||||||
export type { NotificationChannel } from './models/NotificationChannel';
 | 
					export type { NotificationChannel } from './models/NotificationChannel';
 | 
				
			||||||
 | 
					export type { OptionalShippingWarehouseSchema } from './models/OptionalShippingWarehouseSchema';
 | 
				
			||||||
export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
 | 
					export type { PaginationInfoSchema } from './models/PaginationInfoSchema';
 | 
				
			||||||
export type { PalletSchema } from './models/PalletSchema';
 | 
					export type { PalletSchema } from './models/PalletSchema';
 | 
				
			||||||
 | 
					export type { ParsedCityBreakdownSchema } from './models/ParsedCityBreakdownSchema';
 | 
				
			||||||
 | 
					export type { ParseDealsExcelResponse } from './models/ParseDealsExcelResponse';
 | 
				
			||||||
 | 
					export type { ParsedProductRowSchema } from './models/ParsedProductRowSchema';
 | 
				
			||||||
export type { PassportImageSchema } from './models/PassportImageSchema';
 | 
					export type { PassportImageSchema } from './models/PassportImageSchema';
 | 
				
			||||||
export type { PaymentRecordCreateSchema } from './models/PaymentRecordCreateSchema';
 | 
					export type { PaymentRecordCreateSchema } from './models/PaymentRecordCreateSchema';
 | 
				
			||||||
export type { PaymentRecordGetSchema } from './models/PaymentRecordGetSchema';
 | 
					export type { PaymentRecordGetSchema } from './models/PaymentRecordGetSchema';
 | 
				
			||||||
@@ -240,6 +248,7 @@ export type { ProductDeleteBarcodeImageResponse } from './models/ProductDeleteBa
 | 
				
			|||||||
export type { ProductDeleteRequest } from './models/ProductDeleteRequest';
 | 
					export type { ProductDeleteRequest } from './models/ProductDeleteRequest';
 | 
				
			||||||
export type { ProductDeleteResponse } from './models/ProductDeleteResponse';
 | 
					export type { ProductDeleteResponse } from './models/ProductDeleteResponse';
 | 
				
			||||||
export type { ProductExistsBarcodeResponse } from './models/ProductExistsBarcodeResponse';
 | 
					export type { ProductExistsBarcodeResponse } from './models/ProductExistsBarcodeResponse';
 | 
				
			||||||
 | 
					export type { ProductFromExcelSchema } from './models/ProductFromExcelSchema';
 | 
				
			||||||
export type { ProductGenerateBarcodeRequest } from './models/ProductGenerateBarcodeRequest';
 | 
					export type { ProductGenerateBarcodeRequest } from './models/ProductGenerateBarcodeRequest';
 | 
				
			||||||
export type { ProductGenerateBarcodeResponse } from './models/ProductGenerateBarcodeResponse';
 | 
					export type { ProductGenerateBarcodeResponse } from './models/ProductGenerateBarcodeResponse';
 | 
				
			||||||
export type { ProductGetBarcodeImageResponse } from './models/ProductGetBarcodeImageResponse';
 | 
					export type { ProductGetBarcodeImageResponse } from './models/ProductGetBarcodeImageResponse';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								src/client/models/Body_parse_deals_excel.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/client/models/Body_parse_deals_excel.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type Body_parse_deals_excel = {
 | 
				
			||||||
 | 
					    upload_file: Blob;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/client/models/CityBreakdownFromExcelSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/client/models/CityBreakdownFromExcelSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { BaseMarketplaceSchema } from './BaseMarketplaceSchema';
 | 
				
			||||||
 | 
					import type { OptionalShippingWarehouseSchema } from './OptionalShippingWarehouseSchema';
 | 
				
			||||||
 | 
					export type CityBreakdownFromExcelSchema = {
 | 
				
			||||||
 | 
					    baseMarketplace: BaseMarketplaceSchema;
 | 
				
			||||||
 | 
					    shippingWarehouse: OptionalShippingWarehouseSchema;
 | 
				
			||||||
 | 
					    quantity: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/models/CreateDealsFromExcelRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/CreateDealsFromExcelRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { ProductFromExcelSchema } from './ProductFromExcelSchema';
 | 
				
			||||||
 | 
					export type CreateDealsFromExcelRequest = {
 | 
				
			||||||
 | 
					    clientId: number;
 | 
				
			||||||
 | 
					    products: Array<ProductFromExcelSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/CreateDealsFromExcelResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/CreateDealsFromExcelResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type CreateDealsFromExcelResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/OptionalShippingWarehouseSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/OptionalShippingWarehouseSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type OptionalShippingWarehouseSchema = {
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					    id?: (number | null);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/models/ParseDealsExcelResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/ParseDealsExcelResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { ParsedProductRowSchema } from './ParsedProductRowSchema';
 | 
				
			||||||
 | 
					export type ParseDealsExcelResponse = {
 | 
				
			||||||
 | 
					    rows: Array<ParsedProductRowSchema>;
 | 
				
			||||||
 | 
					    errors: Array<string>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/client/models/ParsedCityBreakdownSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/client/models/ParsedCityBreakdownSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { BaseMarketplaceSchema } from './BaseMarketplaceSchema';
 | 
				
			||||||
 | 
					import type { OptionalShippingWarehouseSchema } from './OptionalShippingWarehouseSchema';
 | 
				
			||||||
 | 
					export type ParsedCityBreakdownSchema = {
 | 
				
			||||||
 | 
					    baseMarketplace: BaseMarketplaceSchema;
 | 
				
			||||||
 | 
					    shippingWarehouse: OptionalShippingWarehouseSchema;
 | 
				
			||||||
 | 
					    quantity: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/client/models/ParsedProductRowSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/client/models/ParsedProductRowSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { ParsedCityBreakdownSchema } from './ParsedCityBreakdownSchema';
 | 
				
			||||||
 | 
					import type { ProductSchema } from './ProductSchema';
 | 
				
			||||||
 | 
					export type ParsedProductRowSchema = {
 | 
				
			||||||
 | 
					    barcode: string;
 | 
				
			||||||
 | 
					    products: Array<ProductSchema>;
 | 
				
			||||||
 | 
					    breakdowns: Array<ParsedCityBreakdownSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/models/ProductFromExcelSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/ProductFromExcelSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { CityBreakdownFromExcelSchema } from './CityBreakdownFromExcelSchema';
 | 
				
			||||||
 | 
					export type ProductFromExcelSchema = {
 | 
				
			||||||
 | 
					    productId: number;
 | 
				
			||||||
 | 
					    citiesBreakdown: Array<CityBreakdownFromExcelSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,6 +2,9 @@
 | 
				
			|||||||
/* istanbul ignore file */
 | 
					/* istanbul ignore file */
 | 
				
			||||||
/* tslint:disable */
 | 
					/* tslint:disable */
 | 
				
			||||||
/* eslint-disable */
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { Body_parse_deals_excel } from '../models/Body_parse_deals_excel';
 | 
				
			||||||
 | 
					import type { CreateDealsFromExcelRequest } from '../models/CreateDealsFromExcelRequest';
 | 
				
			||||||
 | 
					import type { CreateDealsFromExcelResponse } from '../models/CreateDealsFromExcelResponse';
 | 
				
			||||||
import type { DealAddKitRequest } from '../models/DealAddKitRequest';
 | 
					import type { DealAddKitRequest } from '../models/DealAddKitRequest';
 | 
				
			||||||
import type { DealAddKitResponse } from '../models/DealAddKitResponse';
 | 
					import type { DealAddKitResponse } from '../models/DealAddKitResponse';
 | 
				
			||||||
import type { DealAddProductRequest } from '../models/DealAddProductRequest';
 | 
					import type { DealAddProductRequest } from '../models/DealAddProductRequest';
 | 
				
			||||||
@@ -66,6 +69,7 @@ import type { GetDealProductsBarcodesPdfRequest } from '../models/GetDealProduct
 | 
				
			|||||||
import type { GetDealProductsBarcodesPdfResponse } from '../models/GetDealProductsBarcodesPdfResponse';
 | 
					import type { GetDealProductsBarcodesPdfResponse } from '../models/GetDealProductsBarcodesPdfResponse';
 | 
				
			||||||
import type { ManageEmployeeRequest } from '../models/ManageEmployeeRequest';
 | 
					import type { ManageEmployeeRequest } from '../models/ManageEmployeeRequest';
 | 
				
			||||||
import type { ManageEmployeeResponse } from '../models/ManageEmployeeResponse';
 | 
					import type { ManageEmployeeResponse } from '../models/ManageEmployeeResponse';
 | 
				
			||||||
 | 
					import type { ParseDealsExcelResponse } from '../models/ParseDealsExcelResponse';
 | 
				
			||||||
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';
 | 
				
			||||||
@@ -426,6 +430,46 @@ export class DealService {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Parse Deals Excel
 | 
				
			||||||
 | 
					     * @returns ParseDealsExcelResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static parseDealsExcel({
 | 
				
			||||||
 | 
					        formData,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        formData: Body_parse_deals_excel,
 | 
				
			||||||
 | 
					    }): CancelablePromise<ParseDealsExcelResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/prefill/excel/parse',
 | 
				
			||||||
 | 
					            formData: formData,
 | 
				
			||||||
 | 
					            mediaType: 'multipart/form-data',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create Deals From Excel
 | 
				
			||||||
 | 
					     * @returns CreateDealsFromExcelResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static createDealsExcel({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: CreateDealsFromExcelRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<CreateDealsFromExcelResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/prefill/excel/create',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Services Add
 | 
					     * Services Add
 | 
				
			||||||
     * @returns DealAddServicesResponse Successful Response
 | 
					     * @returns DealAddServicesResponse Successful Response
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import classNames from "classnames";
 | 
				
			|||||||
import { getPluralForm } from "../../../shared/lib/utils.ts";
 | 
					import { getPluralForm } from "../../../shared/lib/utils.ts";
 | 
				
			||||||
import { groupBy, has, sum, uniq } from "lodash";
 | 
					import { groupBy, has, sum, uniq } from "lodash";
 | 
				
			||||||
import { DealGroupView } from "../DealGroupView/DealGroupView.tsx";
 | 
					import { DealGroupView } from "../DealGroupView/DealGroupView.tsx";
 | 
				
			||||||
 | 
					import CreateDealsFromFileButton from "../CreateDealsFromFileButton/CreateDealsFromFileButton.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
    droppableId: string;
 | 
					    droppableId: string;
 | 
				
			||||||
@@ -181,8 +182,10 @@ export const Board: FC<Props> = ({
 | 
				
			|||||||
                        )}
 | 
					                        )}
 | 
				
			||||||
                        {...provided.droppableProps}>
 | 
					                        {...provided.droppableProps}>
 | 
				
			||||||
                        {withCreateButton && (
 | 
					                        {withCreateButton && (
 | 
				
			||||||
                            <CreateDealButton onClick={() => {
 | 
					                            <>
 | 
				
			||||||
                            }} />
 | 
					                                <CreateDealButton />
 | 
				
			||||||
 | 
					                                <CreateDealsFromFileButton />
 | 
				
			||||||
 | 
					                            </>
 | 
				
			||||||
                        )}
 | 
					                        )}
 | 
				
			||||||
                        {getDealsAndGroups().map(obj => {
 | 
					                        {getDealsAndGroups().map(obj => {
 | 
				
			||||||
                            if (isGroup(obj)) {
 | 
					                            if (isGroup(obj)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { FC, useState } from "react";
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import styles from "./CreateDealButton.module.css";
 | 
					import styles from "./CreateDealButton.module.css";
 | 
				
			||||||
import { Text, Transition } from "@mantine/core";
 | 
					import { Text, Transition } from "@mantine/core";
 | 
				
			||||||
@@ -8,10 +8,7 @@ import { useQueryClient } from "@tanstack/react-query";
 | 
				
			|||||||
import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
 | 
					import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
 | 
				
			||||||
import { usePrefillDealContext } from "../../../pages/LeadsPage/contexts/PrefillDealContext.tsx";
 | 
					import { usePrefillDealContext } from "../../../pages/LeadsPage/contexts/PrefillDealContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					const CreateDealButton = () => {
 | 
				
			||||||
    onClick: () => void;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
const CreateDealButton: FC<Props> = () => {
 | 
					 | 
				
			||||||
    const [isCreating, setIsCreating] = useState(false);
 | 
					    const [isCreating, setIsCreating] = useState(false);
 | 
				
			||||||
    const [isTransitionEnded, setIsTransitionEnded] = useState(true);
 | 
					    const [isTransitionEnded, setIsTransitionEnded] = useState(true);
 | 
				
			||||||
    const queryClient = useQueryClient();
 | 
					    const queryClient = useQueryClient();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					.container {
 | 
				
			||||||
 | 
					    /*background-color: red;*/
 | 
				
			||||||
 | 
					    min-height: 5rem;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    align-items: stretch;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    border: dashed var(--item-border-size) var(--mantine-color-default-border);
 | 
				
			||||||
 | 
					    border-radius: var(--item-border-radius);
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.container:hover {
 | 
				
			||||||
 | 
					    background-color: light-dark(
 | 
				
			||||||
 | 
					        var(--mantine-color-default-hover),
 | 
				
			||||||
 | 
					        var(--mantine-color-gray-filled-hover)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import styles from "./CreateDealsFromFileButton.module.css";
 | 
				
			||||||
 | 
					import { Text } from "@mantine/core";
 | 
				
			||||||
 | 
					import { usePrefillDealsWithExcelContext } from "../../../pages/LeadsPage/contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CreateDealsFromFileButton = () => {
 | 
				
			||||||
 | 
					    const { prefillWithExcelOnOpen } = usePrefillDealsWithExcelContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					            className={styles["container"]}
 | 
				
			||||||
 | 
					            onClick={prefillWithExcelOnOpen}>
 | 
				
			||||||
 | 
					            <Text>Добавление из файла</Text>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CreateDealsFromFileButton;
 | 
				
			||||||
							
								
								
									
										86
									
								
								src/components/ExcelDropzone/ExcelDropzone.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/components/ExcelDropzone/ExcelDropzone.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					import { Dropzone, DropzoneProps, FileWithPath, MIME_TYPES } from "@mantine/dropzone";
 | 
				
			||||||
 | 
					import { FC } from "react";
 | 
				
			||||||
 | 
					import { Fieldset, Flex, Group, Loader, rem, Text } from "@mantine/core";
 | 
				
			||||||
 | 
					import { IconFileExcel, IconUpload, IconX } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import UseExcelDropzone from "../../types/UseExcelDropzone.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface RestProps {
 | 
				
			||||||
 | 
					    dropzone: UseExcelDropzone;
 | 
				
			||||||
 | 
					    onDrop: (files: FileWithPath[]) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = RestProps & Omit<DropzoneProps, "onDrop">;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ExcelDropzone: FC<Props> = (props: Props) => {
 | 
				
			||||||
 | 
					    const { isLoading } = props.dropzone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const getBody = () => {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Dropzone
 | 
				
			||||||
 | 
					                {...props}
 | 
				
			||||||
 | 
					                accept={[
 | 
				
			||||||
 | 
					                    MIME_TYPES.xlsx,
 | 
				
			||||||
 | 
					                ]}
 | 
				
			||||||
 | 
					                multiple={false}
 | 
				
			||||||
 | 
					                onDrop={props.onDrop}>
 | 
				
			||||||
 | 
					                <Group
 | 
				
			||||||
 | 
					                    justify="center"
 | 
				
			||||||
 | 
					                    gap="xl"
 | 
				
			||||||
 | 
					                    style={{ pointerEvents: "none" }}>
 | 
				
			||||||
 | 
					                    <Dropzone.Accept>
 | 
				
			||||||
 | 
					                        <IconUpload
 | 
				
			||||||
 | 
					                            style={{
 | 
				
			||||||
 | 
					                                width: rem(52),
 | 
				
			||||||
 | 
					                                height: rem(52),
 | 
				
			||||||
 | 
					                                color: "var(--mantine-color-blue-6)",
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            stroke={1.5}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </Dropzone.Accept>
 | 
				
			||||||
 | 
					                    <Dropzone.Reject>
 | 
				
			||||||
 | 
					                        <IconX
 | 
				
			||||||
 | 
					                            style={{
 | 
				
			||||||
 | 
					                                width: rem(52),
 | 
				
			||||||
 | 
					                                height: rem(52),
 | 
				
			||||||
 | 
					                                color: "var(--mantine-color-red-6)",
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            stroke={1.5}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </Dropzone.Reject>
 | 
				
			||||||
 | 
					                    <Dropzone.Idle>
 | 
				
			||||||
 | 
					                        <IconFileExcel
 | 
				
			||||||
 | 
					                            style={{
 | 
				
			||||||
 | 
					                                width: rem(52),
 | 
				
			||||||
 | 
					                                height: rem(52),
 | 
				
			||||||
 | 
					                                color: "var(--mantine-color-dimmed)",
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            stroke={1.5}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </Dropzone.Idle>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <div style={{ textAlign: "center" }}>
 | 
				
			||||||
 | 
					                        <Text
 | 
				
			||||||
 | 
					                            size="xl"
 | 
				
			||||||
 | 
					                            inline>
 | 
				
			||||||
 | 
					                            Перенесите или нажмите чтоб выбрать файл формата xlsx
 | 
				
			||||||
 | 
					                        </Text>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </Group>
 | 
				
			||||||
 | 
					            </Dropzone>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Flex
 | 
				
			||||||
 | 
					            gap={rem(10)}
 | 
				
			||||||
 | 
					            direction={"column"}>
 | 
				
			||||||
 | 
					            <Fieldset legend={"Файл"}>
 | 
				
			||||||
 | 
					                <Flex justify={"center"}>
 | 
				
			||||||
 | 
					                    {isLoading ? <Loader /> : getBody()}
 | 
				
			||||||
 | 
					                </Flex>
 | 
				
			||||||
 | 
					            </Fieldset>
 | 
				
			||||||
 | 
					        </Flex>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ExcelDropzone;
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { FC } from "react";
 | 
					import { FC, ReactNode } from "react";
 | 
				
			||||||
import { Select } from "@mantine/core";
 | 
					import { Select } from "@mantine/core";
 | 
				
			||||||
import { ClientSchema } from "../../../client";
 | 
					import { ClientSchema } from "../../../client";
 | 
				
			||||||
import useClientsList from "../../../pages/ClientsPage/hooks/useClientsList.tsx";
 | 
					import useClientsList from "../../../pages/ClientsPage/hooks/useClientsList.tsx";
 | 
				
			||||||
@@ -7,8 +7,10 @@ type Props = {
 | 
				
			|||||||
    value?: ClientSchema;
 | 
					    value?: ClientSchema;
 | 
				
			||||||
    onChange: (client: ClientSchema) => void;
 | 
					    onChange: (client: ClientSchema) => void;
 | 
				
			||||||
    withLabel?: boolean;
 | 
					    withLabel?: boolean;
 | 
				
			||||||
 | 
					    error?: string;
 | 
				
			||||||
 | 
					    inputContainer?: (children: ReactNode) => ReactNode;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const ClientSelect: FC<Props> = ({ value, onChange, withLabel = false }) => {
 | 
					const ClientSelect: FC<Props> = ({ value, onChange, error, inputContainer, withLabel = false }) => {
 | 
				
			||||||
    const { clients } = useClientsList();
 | 
					    const { clients } = useClientsList();
 | 
				
			||||||
    const options = clients.map(client => ({
 | 
					    const options = clients.map(client => ({
 | 
				
			||||||
        label: client.name,
 | 
					        label: client.name,
 | 
				
			||||||
@@ -33,6 +35,8 @@ const ClientSelect: FC<Props> = ({ value, onChange, withLabel = false }) => {
 | 
				
			|||||||
            }}
 | 
					            }}
 | 
				
			||||||
            data={options}
 | 
					            data={options}
 | 
				
			||||||
            label={withLabel && "Клиент"}
 | 
					            label={withLabel && "Клиент"}
 | 
				
			||||||
 | 
					            error={error}
 | 
				
			||||||
 | 
					            inputContainer={inputContainer}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										150
									
								
								src/pages/LeadsPage/contexts/PrefillDealsWithExcelContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/pages/LeadsPage/contexts/PrefillDealsWithExcelContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					import { createContext, FC, useContext, useState } from "react";
 | 
				
			||||||
 | 
					import { useDisclosure } from "@mantine/hooks";
 | 
				
			||||||
 | 
					import { DealsWithExcelForm, ProductExcelData } from "../drawers/PrefillDealWithExcelDrawer/types.tsx";
 | 
				
			||||||
 | 
					import { FileWithPath } from "@mantine/dropzone";
 | 
				
			||||||
 | 
					import { notifications } from "../../../shared/lib/notifications.ts";
 | 
				
			||||||
 | 
					import { DealService, type ProductFromExcelSchema, ProductSchema } from "../../../client";
 | 
				
			||||||
 | 
					import UseExcelDropzone from "../../../types/UseExcelDropzone.tsx";
 | 
				
			||||||
 | 
					import { useForm, UseFormReturnType } from "@mantine/form";
 | 
				
			||||||
 | 
					import { useDealPageContext } from "./DealPageContext.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PrefillDealsWithExcelContextState = {
 | 
				
			||||||
 | 
					    prefillWithExcelOpened: boolean;
 | 
				
			||||||
 | 
					    prefillWithExcelOnClose: () => void;
 | 
				
			||||||
 | 
					    prefillWithExcelOnOpen: () => void;
 | 
				
			||||||
 | 
					    barcodeProductsMap: Map<string, ProductExcelData>,
 | 
				
			||||||
 | 
					    onProductSelectChange: (barcode: string, selectedProduct: ProductSchema) => void,
 | 
				
			||||||
 | 
					    onDrop: (files: FileWithPath[]) => void;
 | 
				
			||||||
 | 
					    excelDropzone: UseExcelDropzone;
 | 
				
			||||||
 | 
					    createDeals: (values: DealsWithExcelForm) => void;
 | 
				
			||||||
 | 
					    form: UseFormReturnType<DealsWithExcelForm>;
 | 
				
			||||||
 | 
					    errors: string[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PrefillDealsWithExcelContext = createContext<PrefillDealsWithExcelContextState | undefined>(
 | 
				
			||||||
 | 
					    undefined,
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					const usePrefillDealsWithExcelContextState = () => {
 | 
				
			||||||
 | 
					    const [prefillWithExcelOpened, { open, close }] = useDisclosure(false);
 | 
				
			||||||
 | 
					    const { refetchDeals } = useDealPageContext();
 | 
				
			||||||
 | 
					    const [isLoading, setIsLoading] = useState(false);
 | 
				
			||||||
 | 
					    const [errors, setErrors] = useState<string[]>([]);
 | 
				
			||||||
 | 
					    const excelDropzone: UseExcelDropzone = {
 | 
				
			||||||
 | 
					        isLoading,
 | 
				
			||||||
 | 
					        setIsLoading,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const form = useForm<DealsWithExcelForm>({
 | 
				
			||||||
 | 
					        validate: {
 | 
				
			||||||
 | 
					            client: client => !client && "Выберите клиента",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [barcodeProductsMap, setBarcodeProductsMap] = useState<Map<string, ProductExcelData>>(new Map());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onDrop = (files: FileWithPath[]) => {
 | 
				
			||||||
 | 
					        if (files.length > 1) {
 | 
				
			||||||
 | 
					            notifications.error({ message: "Прикрепите одно изображение" });
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const file = files[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setIsLoading(true);
 | 
				
			||||||
 | 
					        DealService.parseDealsExcel({
 | 
				
			||||||
 | 
					            formData: {
 | 
				
			||||||
 | 
					                upload_file: file,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					            .then(res => {
 | 
				
			||||||
 | 
					                const barcodeProductsMap = new Map();
 | 
				
			||||||
 | 
					                res.rows.forEach((row) => {
 | 
				
			||||||
 | 
					                    const productsData: ProductExcelData = row;
 | 
				
			||||||
 | 
					                    productsData.selectedProduct = productsData.products[0];
 | 
				
			||||||
 | 
					                    barcodeProductsMap.set(row.barcode, row);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                setBarcodeProductsMap(barcodeProductsMap);
 | 
				
			||||||
 | 
					                setErrors(res.errors);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(error => {
 | 
				
			||||||
 | 
					                notifications.error({ message: error.toString() });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .finally(() => setIsLoading(false));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onProductSelectChange = (barcode: string, selectedProduct: ProductSchema) => {
 | 
				
			||||||
 | 
					        const newBarcodeProductsMap = new Map(barcodeProductsMap);
 | 
				
			||||||
 | 
					        const productsData = newBarcodeProductsMap.get(barcode);
 | 
				
			||||||
 | 
					        if (!productsData) return;
 | 
				
			||||||
 | 
					        productsData.selectedProduct = selectedProduct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        newBarcodeProductsMap.set(
 | 
				
			||||||
 | 
					            barcode,
 | 
				
			||||||
 | 
					            productsData,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        setBarcodeProductsMap(newBarcodeProductsMap);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const prefillWithExcelOnClose = () => {
 | 
				
			||||||
 | 
					        close();
 | 
				
			||||||
 | 
					        setBarcodeProductsMap(new Map());
 | 
				
			||||||
 | 
					        form.reset();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const createDeals = (values: DealsWithExcelForm) => {
 | 
				
			||||||
 | 
					        const products: ProductFromExcelSchema[] = barcodeProductsMap.entries().map(([, productData]) => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                productId: productData.selectedProduct!.id,
 | 
				
			||||||
 | 
					                citiesBreakdown: productData.breakdowns,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }).toArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DealService.createDealsExcel({
 | 
				
			||||||
 | 
					            requestBody: {
 | 
				
			||||||
 | 
					                products,
 | 
				
			||||||
 | 
					                clientId: values.client?.id ?? -1,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					            .then(({ ok, message }) => {
 | 
				
			||||||
 | 
					                notifications.guess(ok, { message });
 | 
				
			||||||
 | 
					                if (ok) prefillWithExcelOnClose();
 | 
				
			||||||
 | 
					                refetchDeals();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(err => console.log(err));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        prefillWithExcelOpened,
 | 
				
			||||||
 | 
					        prefillWithExcelOnClose,
 | 
				
			||||||
 | 
					        prefillWithExcelOnOpen: open,
 | 
				
			||||||
 | 
					        barcodeProductsMap,
 | 
				
			||||||
 | 
					        onProductSelectChange,
 | 
				
			||||||
 | 
					        onDrop,
 | 
				
			||||||
 | 
					        excelDropzone,
 | 
				
			||||||
 | 
					        createDeals,
 | 
				
			||||||
 | 
					        form,
 | 
				
			||||||
 | 
					        errors,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PrefillDealsWithExcelContextProviderProps = {
 | 
				
			||||||
 | 
					    children: React.ReactNode;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const PrefillDealsWithExcelContextProvider: FC<PrefillDealsWithExcelContextProviderProps> = ({ children }) => {
 | 
				
			||||||
 | 
					    const state = usePrefillDealsWithExcelContextState();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <PrefillDealsWithExcelContext.Provider value={state}>
 | 
				
			||||||
 | 
					            {children}
 | 
				
			||||||
 | 
					        </PrefillDealsWithExcelContext.Provider>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const usePrefillDealsWithExcelContext = () => {
 | 
				
			||||||
 | 
					    const context = useContext(PrefillDealsWithExcelContext);
 | 
				
			||||||
 | 
					    if (!context) {
 | 
				
			||||||
 | 
					        throw new Error(
 | 
				
			||||||
 | 
					            "usePrefillDealsWithExcelContext must be used within a PrefillDealsWithExcelContextProvider",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return context;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					.container {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: row;
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    max-height: 95vh;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.deal-container {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.deal-container-wrapper {
 | 
				
			||||||
 | 
					    border: dashed var(--item-border-size) var(--mantine-color-default-border);
 | 
				
			||||||
 | 
					    border-radius: var(--item-border-radius);
 | 
				
			||||||
 | 
					    padding: rem(10);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.deal-container-buttons {
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    margin-top: auto;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.top-panel {
 | 
				
			||||||
 | 
					    padding-bottom: rem(9);
 | 
				
			||||||
 | 
					    gap: rem(10);
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					import { Drawer, rem } from "@mantine/core";
 | 
				
			||||||
 | 
					import ExcelDropzone from "../../../../components/ExcelDropzone/ExcelDropzone.tsx";
 | 
				
			||||||
 | 
					import styles from "../PrefillDealWithExcelDrawer/PrefillDealsWithExcelDrawer.module.css";
 | 
				
			||||||
 | 
					import { usePrefillDealsWithExcelContext } from "../../contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					import ProductsPreview from "./components/ProductsPreview.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PrefillDealsWithExcelDrawer = () => {
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					        prefillWithExcelOpened,
 | 
				
			||||||
 | 
					        prefillWithExcelOnClose,
 | 
				
			||||||
 | 
					        barcodeProductsMap,
 | 
				
			||||||
 | 
					        onDrop,
 | 
				
			||||||
 | 
					        excelDropzone,
 | 
				
			||||||
 | 
					    } = usePrefillDealsWithExcelContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const getBody = () => {
 | 
				
			||||||
 | 
					        if (barcodeProductsMap?.size === 0) {
 | 
				
			||||||
 | 
					            return <ExcelDropzone dropzone={excelDropzone} onDrop={onDrop} />;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return <ProductsPreview />;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Drawer
 | 
				
			||||||
 | 
					            size={"calc(77vw)"}
 | 
				
			||||||
 | 
					            position={"right"}
 | 
				
			||||||
 | 
					            onClose={prefillWithExcelOnClose}
 | 
				
			||||||
 | 
					            removeScrollProps={{ allowPinchZoom: true }}
 | 
				
			||||||
 | 
					            withCloseButton={false}
 | 
				
			||||||
 | 
					            opened={prefillWithExcelOpened}
 | 
				
			||||||
 | 
					            styles={{
 | 
				
			||||||
 | 
					                body: {
 | 
				
			||||||
 | 
					                    height: "100%",
 | 
				
			||||||
 | 
					                    display: "flex",
 | 
				
			||||||
 | 
					                    flexDirection: "row",
 | 
				
			||||||
 | 
					                    gap: rem(20),
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            <div className={styles["deal-container"]}>
 | 
				
			||||||
 | 
					                {getBody()}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </Drawer>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default PrefillDealsWithExcelDrawer;
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					import { ParsedCityBreakdownSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import { useBreakdownByCityTableColumns } from "../hooks/useBreakdownByCityTableColumns.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    breakdowns: ParsedCityBreakdownSchema[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BreakdownByCityTable = ({ breakdowns }: Props) => {
 | 
				
			||||||
 | 
					    const columns = useBreakdownByCityTableColumns();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseTable
 | 
				
			||||||
 | 
					            data={breakdowns}
 | 
				
			||||||
 | 
					            columns={columns}
 | 
				
			||||||
 | 
					            w={"30%"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            restProps={{
 | 
				
			||||||
 | 
					                enableSorting: false,
 | 
				
			||||||
 | 
					                enableRowActions: false,
 | 
				
			||||||
 | 
					                enableTopToolbar: false,
 | 
				
			||||||
 | 
					                enableColumnActions: false,
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default BreakdownByCityTable;
 | 
				
			||||||
@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import { usePrefillDealsWithExcelContext } from "../../../contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					import { Text, Tooltip } from "@mantine/core";
 | 
				
			||||||
 | 
					import { IconAlertCircle, IconCircleCheck } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ParsingResultsTooltip = () => {
 | 
				
			||||||
 | 
					    const { errors } = usePrefillDealsWithExcelContext();
 | 
				
			||||||
 | 
					    const isError = errors.length !== 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const errorLines = errors.map((error, i) => <Text key={i}>{error}</Text>);
 | 
				
			||||||
 | 
					    const tooltipData = isError ? errorLines : "Ошибок при обработке нет";
 | 
				
			||||||
 | 
					    const color = isError ? "red" : "grey";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Tooltip
 | 
				
			||||||
 | 
					            label={tooltipData}
 | 
				
			||||||
 | 
					            multiline
 | 
				
			||||||
 | 
					            w={350}
 | 
				
			||||||
 | 
					            withArrow
 | 
				
			||||||
 | 
					            color={color}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            {isError ? (
 | 
				
			||||||
 | 
					                <IconAlertCircle color={"red"}/>
 | 
				
			||||||
 | 
					            ) : (
 | 
				
			||||||
 | 
					                <IconCircleCheck color={"green"}/>
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					        </Tooltip>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ParsingResultsTooltip;
 | 
				
			||||||
@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					import styles from "../PrefillDealsWithExcelDrawer.module.css";
 | 
				
			||||||
 | 
					import ProductsTable from "./ProductsTable.tsx";
 | 
				
			||||||
 | 
					import { usePrefillDealsWithExcelContext } from "../../../contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					import { Box, Button, Flex, Group, Stack, Title } from "@mantine/core";
 | 
				
			||||||
 | 
					import { ProductExcelData } from "../types.tsx";
 | 
				
			||||||
 | 
					import BreakdownByCityTable from "./BreakdownByCityTable.tsx";
 | 
				
			||||||
 | 
					import ClientSelect from "../../../../../components/Selects/ClientSelect/ClientSelect.tsx";
 | 
				
			||||||
 | 
					import ParsingResultsTooltip from "./ParsingResultsTooltip.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProductsPreview = () => {
 | 
				
			||||||
 | 
					    const { barcodeProductsMap, createDeals, form } = usePrefillDealsWithExcelContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const getTitle = (barcode: string, productsData: ProductExcelData) => {
 | 
				
			||||||
 | 
					        if (productsData.products.length === 1) {
 | 
				
			||||||
 | 
					            return `Товар со штрихкодом ${barcode}`;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return `Товары со штрихкодом ${barcode}`;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const getProductsData = () => {
 | 
				
			||||||
 | 
					        return barcodeProductsMap.entries().map(([barcode, productsData]) => (
 | 
				
			||||||
 | 
					                <div key={barcode} className={styles["deal-container-wrapper"]}>
 | 
				
			||||||
 | 
					                    <Stack>
 | 
				
			||||||
 | 
					                        <Title order={5}>
 | 
				
			||||||
 | 
					                            {getTitle(barcode, productsData)}
 | 
				
			||||||
 | 
					                        </Title>
 | 
				
			||||||
 | 
					                        <Flex direction={"row"} gap={"md"} flex={10}>
 | 
				
			||||||
 | 
					                            <Box flex={7}>
 | 
				
			||||||
 | 
					                                <ProductsTable barcode={barcode} productsData={productsData} />
 | 
				
			||||||
 | 
					                            </Box>
 | 
				
			||||||
 | 
					                            <Box flex={3}>
 | 
				
			||||||
 | 
					                                <BreakdownByCityTable breakdowns={productsData.breakdowns} />
 | 
				
			||||||
 | 
					                            </Box>
 | 
				
			||||||
 | 
					                        </Flex>
 | 
				
			||||||
 | 
					                    </Stack>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ).toArray();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Stack gap={"md"}>
 | 
				
			||||||
 | 
					            <Title order={3}>Предпросмотр</Title>
 | 
				
			||||||
 | 
					            <form onSubmit={form.onSubmit((values) => createDeals(values))}>
 | 
				
			||||||
 | 
					                <ClientSelect
 | 
				
			||||||
 | 
					                    {...form.getInputProps("client")}
 | 
				
			||||||
 | 
					                    inputContainer={(children) => (
 | 
				
			||||||
 | 
					                        <Group align={"flex-start"}>
 | 
				
			||||||
 | 
					                            {children}
 | 
				
			||||||
 | 
					                            <Group>
 | 
				
			||||||
 | 
					                                <Button
 | 
				
			||||||
 | 
					                                    variant="outline"
 | 
				
			||||||
 | 
					                                    type="submit"
 | 
				
			||||||
 | 
					                                >
 | 
				
			||||||
 | 
					                                    Создать сделки
 | 
				
			||||||
 | 
					                                </Button>
 | 
				
			||||||
 | 
					                                <ParsingResultsTooltip />
 | 
				
			||||||
 | 
					                            </Group>
 | 
				
			||||||
 | 
					                        </Group>
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </form>
 | 
				
			||||||
 | 
					            {getProductsData()}
 | 
				
			||||||
 | 
					        </Stack>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ProductsPreview;
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					import { useProductsTableColumns } from "../hooks/useProductsTableColumns.tsx";
 | 
				
			||||||
 | 
					import { ProductExcelData } from "../types.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    barcode: string;
 | 
				
			||||||
 | 
					    productsData: ProductExcelData;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ProductsTable = ({ barcode, productsData }: Props) => {
 | 
				
			||||||
 | 
					    const columns = useProductsTableColumns({ barcode });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseTable
 | 
				
			||||||
 | 
					            data={productsData.products}
 | 
				
			||||||
 | 
					            columns={columns}
 | 
				
			||||||
 | 
					            w={"100%"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            restProps={{
 | 
				
			||||||
 | 
					                enableSorting: false,
 | 
				
			||||||
 | 
					                enableRowActions: false,
 | 
				
			||||||
 | 
					                enableTopToolbar: false,
 | 
				
			||||||
 | 
					                enableColumnActions: false,
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ProductsTable;
 | 
				
			||||||
@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import { useMemo } from "react";
 | 
				
			||||||
 | 
					import { MRT_ColumnDef } from "mantine-react-table";
 | 
				
			||||||
 | 
					import { ParsedCityBreakdownSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import { ActionIcon, Image } from "@mantine/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useBreakdownByCityTableColumns = () => {
 | 
				
			||||||
 | 
					    return useMemo<MRT_ColumnDef<ParsedCityBreakdownSchema>[]>(
 | 
				
			||||||
 | 
					        () => [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "baseMarketplace.iconUrl",
 | 
				
			||||||
 | 
					                header: "Маркетплейс",
 | 
				
			||||||
 | 
					                Cell: ({ cell }) => (
 | 
				
			||||||
 | 
					                    <ActionIcon
 | 
				
			||||||
 | 
					                        radius={"md"}
 | 
				
			||||||
 | 
					                        variant={"transparent"}>
 | 
				
			||||||
 | 
					                        <Image src={cell.getValue()} />
 | 
				
			||||||
 | 
					                    </ActionIcon>
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                size: 10,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "shippingWarehouse.name",
 | 
				
			||||||
 | 
					                header: "Склад отгрузки",
 | 
				
			||||||
 | 
					                size: 10,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "quantity",
 | 
				
			||||||
 | 
					                header: "Количество",
 | 
				
			||||||
 | 
					                size: 10,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					import { useEffect, useMemo, useState } from "react";
 | 
				
			||||||
 | 
					import { MRT_ColumnDef } from "mantine-react-table";
 | 
				
			||||||
 | 
					import { ProductSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import { Radio } from "@mantine/core";
 | 
				
			||||||
 | 
					import { usePrefillDealsWithExcelContext } from "../../../contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					import { ProductExcelData } from "../types.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    barcode: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useProductsTableColumns = ({ barcode }: Props) => {
 | 
				
			||||||
 | 
					    const { onProductSelectChange, barcodeProductsMap } = usePrefillDealsWithExcelContext();
 | 
				
			||||||
 | 
					    const [productData, setProductData] = useState<ProductExcelData>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        setProductData(barcodeProductsMap.get(barcode));
 | 
				
			||||||
 | 
					    }, [barcodeProductsMap]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return useMemo<MRT_ColumnDef<ProductSchema>[]>(
 | 
				
			||||||
 | 
					        () => [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                header: "Выбор",
 | 
				
			||||||
 | 
					                size: 10,
 | 
				
			||||||
 | 
					                Cell: ({ row }) => {
 | 
				
			||||||
 | 
					                    return (
 | 
				
			||||||
 | 
					                        <Radio
 | 
				
			||||||
 | 
					                            checked={productData?.selectedProduct?.id === row.original.id}
 | 
				
			||||||
 | 
					                            onChange={() => onProductSelectChange(barcode, row.original)}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "article",
 | 
				
			||||||
 | 
					                header: "Артикул",
 | 
				
			||||||
 | 
					                size: 20,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "name",
 | 
				
			||||||
 | 
					                header: "Название",
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "brand",
 | 
				
			||||||
 | 
					                header: "Бренд",
 | 
				
			||||||
 | 
					                size: 30,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "color",
 | 
				
			||||||
 | 
					                header: "Цвет",
 | 
				
			||||||
 | 
					                size: 30,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "size",
 | 
				
			||||||
 | 
					                header: "Размер",
 | 
				
			||||||
 | 
					                size: 10,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [productData],
 | 
				
			||||||
 | 
					    ).filter(columnDef => (
 | 
				
			||||||
 | 
					        !(columnDef.header === "Выбор" && (productData?.products.length ?? 0) === 1)
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import { ClientSchema, type ParsedCityBreakdownSchema, ProductSchema } from "../../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type ProductExcelData = {
 | 
				
			||||||
 | 
					    products: ProductSchema[];
 | 
				
			||||||
 | 
					    breakdowns: ParsedCityBreakdownSchema[];
 | 
				
			||||||
 | 
					    selectedProduct?: ProductSchema;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type DealsWithExcelForm = {
 | 
				
			||||||
 | 
					    client?: ClientSchema;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -23,6 +23,8 @@ import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
 | 
				
			|||||||
import DealPrefillDrawer from "../drawers/DealPrefillDrawer/DealPrefillDrawer.tsx";
 | 
					import DealPrefillDrawer from "../drawers/DealPrefillDrawer/DealPrefillDrawer.tsx";
 | 
				
			||||||
import { PrefillDealContextProvider } from "../contexts/PrefillDealContext.tsx";
 | 
					import { PrefillDealContextProvider } from "../contexts/PrefillDealContext.tsx";
 | 
				
			||||||
import { useParams } from "@tanstack/react-router";
 | 
					import { useParams } from "@tanstack/react-router";
 | 
				
			||||||
 | 
					import { PrefillDealsWithExcelContextProvider } from "../contexts/PrefillDealsWithExcelContext.tsx";
 | 
				
			||||||
 | 
					import PrefillDealsWithExcelDrawer from "../drawers/PrefillDealWithExcelDrawer/PrefillDealsWithExcelDrawer.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum DisplayMode {
 | 
					enum DisplayMode {
 | 
				
			||||||
    BOARD,
 | 
					    BOARD,
 | 
				
			||||||
@@ -401,6 +403,7 @@ export const LeadsPage: FC = () => {
 | 
				
			|||||||
                    await refetch();
 | 
					                    await refetch();
 | 
				
			||||||
                }}>
 | 
					                }}>
 | 
				
			||||||
                <PrefillDealContextProvider>
 | 
					                <PrefillDealContextProvider>
 | 
				
			||||||
 | 
					                    <PrefillDealsWithExcelContextProvider>
 | 
				
			||||||
                        <PageBlock style={{ flex: 0 }}>
 | 
					                        <PageBlock style={{ flex: 0 }}>
 | 
				
			||||||
                            <Flex
 | 
					                            <Flex
 | 
				
			||||||
                                align={"center"}
 | 
					                                align={"center"}
 | 
				
			||||||
@@ -496,6 +499,8 @@ export const LeadsPage: FC = () => {
 | 
				
			|||||||
                        </PageBlock>
 | 
					                        </PageBlock>
 | 
				
			||||||
                        <DealEditDrawer />
 | 
					                        <DealEditDrawer />
 | 
				
			||||||
                        <DealPrefillDrawer />
 | 
					                        <DealPrefillDrawer />
 | 
				
			||||||
 | 
					                        <PrefillDealsWithExcelDrawer />
 | 
				
			||||||
 | 
					                    </PrefillDealsWithExcelContextProvider>
 | 
				
			||||||
                </PrefillDealContextProvider>
 | 
					                </PrefillDealContextProvider>
 | 
				
			||||||
            </DealPageContextProvider>
 | 
					            </DealPageContextProvider>
 | 
				
			||||||
        </PageBlock>
 | 
					        </PageBlock>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								src/types/UseExcelDropzone.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/types/UseExcelDropzone.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					import { Dispatch, SetStateAction } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UseExcelDropzone = {
 | 
				
			||||||
 | 
					    isLoading: boolean;
 | 
				
			||||||
 | 
					    setIsLoading: Dispatch<SetStateAction<boolean>>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default UseExcelDropzone;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user