feat: assignment of employees to deals
This commit is contained in:
		@@ -9,6 +9,7 @@ export type { OpenAPIConfig } from './core/OpenAPI';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type { AddUserRequest } from './models/AddUserRequest';
 | 
					export type { AddUserRequest } from './models/AddUserRequest';
 | 
				
			||||||
export type { AddUserResponse } from './models/AddUserResponse';
 | 
					export type { AddUserResponse } from './models/AddUserResponse';
 | 
				
			||||||
 | 
					export type { AssignmentSchema } from './models/AssignmentSchema';
 | 
				
			||||||
export type { AuthLoginRequest } from './models/AuthLoginRequest';
 | 
					export type { AuthLoginRequest } from './models/AuthLoginRequest';
 | 
				
			||||||
export type { AuthLoginResponse } from './models/AuthLoginResponse';
 | 
					export type { AuthLoginResponse } from './models/AuthLoginResponse';
 | 
				
			||||||
export type { BarcodeAttributeSchema } from './models/BarcodeAttributeSchema';
 | 
					export type { BarcodeAttributeSchema } from './models/BarcodeAttributeSchema';
 | 
				
			||||||
@@ -189,6 +190,7 @@ export type { GetAllTransactionsRequest } from './models/GetAllTransactionsReque
 | 
				
			|||||||
export type { GetAllTransactionsResponse } from './models/GetAllTransactionsResponse';
 | 
					export type { GetAllTransactionsResponse } from './models/GetAllTransactionsResponse';
 | 
				
			||||||
export type { GetAllTransactionTagsResponse } from './models/GetAllTransactionTagsResponse';
 | 
					export type { GetAllTransactionTagsResponse } from './models/GetAllTransactionTagsResponse';
 | 
				
			||||||
export type { GetAllUsersResponse } from './models/GetAllUsersResponse';
 | 
					export type { GetAllUsersResponse } from './models/GetAllUsersResponse';
 | 
				
			||||||
 | 
					export type { GetAvailableEmployeesToAssignResponse } from './models/GetAvailableEmployeesToAssignResponse';
 | 
				
			||||||
export type { GetAvailableUsersForDepartmentSectionResponse } from './models/GetAvailableUsersForDepartmentSectionResponse';
 | 
					export type { GetAvailableUsersForDepartmentSectionResponse } from './models/GetAvailableUsersForDepartmentSectionResponse';
 | 
				
			||||||
export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest';
 | 
					export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest';
 | 
				
			||||||
export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse';
 | 
					export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse';
 | 
				
			||||||
@@ -215,6 +217,8 @@ export type { GetTransactionTagsResponse } from './models/GetTransactionTagsResp
 | 
				
			|||||||
export type { GetWorkShiftsResponse } from './models/GetWorkShiftsResponse';
 | 
					export type { GetWorkShiftsResponse } from './models/GetWorkShiftsResponse';
 | 
				
			||||||
export type { GroupBillRequestSchema } from './models/GroupBillRequestSchema';
 | 
					export type { GroupBillRequestSchema } from './models/GroupBillRequestSchema';
 | 
				
			||||||
export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
					export type { HTTPValidationError } from './models/HTTPValidationError';
 | 
				
			||||||
 | 
					export type { ManageEmployeeRequest } from './models/ManageEmployeeRequest';
 | 
				
			||||||
 | 
					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';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/client/models/AssignmentSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/AssignmentSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { UserSchema } from './UserSchema';
 | 
				
			||||||
 | 
					export type AssignmentSchema = {
 | 
				
			||||||
 | 
					    user: UserSchema;
 | 
				
			||||||
 | 
					    createdAt: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
/* istanbul ignore file */
 | 
					/* istanbul ignore file */
 | 
				
			||||||
/* tslint:disable */
 | 
					/* tslint:disable */
 | 
				
			||||||
/* eslint-disable */
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { AssignmentSchema } from './AssignmentSchema';
 | 
				
			||||||
import type { BoxSchema } from './BoxSchema';
 | 
					import type { BoxSchema } from './BoxSchema';
 | 
				
			||||||
import type { ClientSchema } from './ClientSchema';
 | 
					import type { ClientSchema } from './ClientSchema';
 | 
				
			||||||
import type { DealBillRequestSchema } from './DealBillRequestSchema';
 | 
					import type { DealBillRequestSchema } from './DealBillRequestSchema';
 | 
				
			||||||
@@ -34,6 +35,7 @@ export type DealSchema = {
 | 
				
			|||||||
    manager?: (UserSchema | null);
 | 
					    manager?: (UserSchema | null);
 | 
				
			||||||
    pallets?: Array<PalletSchema>;
 | 
					    pallets?: Array<PalletSchema>;
 | 
				
			||||||
    boxes?: Array<BoxSchema>;
 | 
					    boxes?: Array<BoxSchema>;
 | 
				
			||||||
 | 
					    assignments?: Array<AssignmentSchema>;
 | 
				
			||||||
    deliveryDate?: (string | null);
 | 
					    deliveryDate?: (string | null);
 | 
				
			||||||
    receivingSlotDate?: (string | null);
 | 
					    receivingSlotDate?: (string | null);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { UserSchema } from './UserSchema';
 | 
				
			||||||
 | 
					export type GetAvailableEmployeesToAssignResponse = {
 | 
				
			||||||
 | 
					    employees: Array<UserSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/models/ManageEmployeeRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/ManageEmployeeRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type ManageEmployeeRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    userId: number;
 | 
				
			||||||
 | 
					    isAssign: boolean;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/ManageEmployeeResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/ManageEmployeeResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do not edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type ManageEmployeeResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -61,8 +61,11 @@ import type { DealUpdateServiceQuantityRequest } from '../models/DealUpdateServi
 | 
				
			|||||||
import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
					import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
				
			||||||
import type { DealUpdateServiceRequest } from '../models/DealUpdateServiceRequest';
 | 
					import type { DealUpdateServiceRequest } from '../models/DealUpdateServiceRequest';
 | 
				
			||||||
import type { DealUpdateServiceResponse } from '../models/DealUpdateServiceResponse';
 | 
					import type { DealUpdateServiceResponse } from '../models/DealUpdateServiceResponse';
 | 
				
			||||||
 | 
					import type { GetAvailableEmployeesToAssignResponse } from '../models/GetAvailableEmployeesToAssignResponse';
 | 
				
			||||||
import type { GetDealProductsBarcodesPdfRequest } from '../models/GetDealProductsBarcodesPdfRequest';
 | 
					import type { GetDealProductsBarcodesPdfRequest } from '../models/GetDealProductsBarcodesPdfRequest';
 | 
				
			||||||
import type { GetDealProductsBarcodesPdfResponse } from '../models/GetDealProductsBarcodesPdfResponse';
 | 
					import type { GetDealProductsBarcodesPdfResponse } from '../models/GetDealProductsBarcodesPdfResponse';
 | 
				
			||||||
 | 
					import type { ManageEmployeeRequest } from '../models/ManageEmployeeRequest';
 | 
				
			||||||
 | 
					import type { ManageEmployeeResponse } from '../models/ManageEmployeeResponse';
 | 
				
			||||||
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';
 | 
				
			||||||
@@ -382,6 +385,47 @@ export class DealService {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Manage Employee
 | 
				
			||||||
 | 
					     * @returns ManageEmployeeResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static manageEmployee({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: ManageEmployeeRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<ManageEmployeeResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/employee',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get Available Employees To Assign
 | 
				
			||||||
 | 
					     * @returns GetAvailableEmployeesToAssignResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static getAvailableEmployeesToAssign({
 | 
				
			||||||
 | 
					        dealId,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        dealId: number,
 | 
				
			||||||
 | 
					    }): CancelablePromise<GetAvailableEmployeesToAssignResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'GET',
 | 
				
			||||||
 | 
					            url: '/deal/employee/available/{deal_id}',
 | 
				
			||||||
 | 
					            path: {
 | 
				
			||||||
 | 
					                'deal_id': dealId,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Services Add
 | 
					     * Services Add
 | 
				
			||||||
     * @returns DealAddServicesResponse Successful Response
 | 
					     * @returns DealAddServicesResponse Successful Response
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@ import ShippingProductModal from "../pages/LeadsPage/tabs/ShippingTab/modals/Shi
 | 
				
			|||||||
import DepartmentModal from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/DepartmentModal.tsx";
 | 
					import DepartmentModal from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/DepartmentModal.tsx";
 | 
				
			||||||
import AddUserToDepartmentModal
 | 
					import AddUserToDepartmentModal
 | 
				
			||||||
    from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/AddUserToDepartmentModal.tsx";
 | 
					    from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/AddUserToDepartmentModal.tsx";
 | 
				
			||||||
 | 
					import AssignUserModal from "../pages/LeadsPage/tabs/EmployeesTab/modals/AssignUserModal.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const modals = {
 | 
					export const modals = {
 | 
				
			||||||
    enterDeadline: EnterDeadlineModal,
 | 
					    enterDeadline: EnterDeadlineModal,
 | 
				
			||||||
@@ -59,4 +60,5 @@ export const modals = {
 | 
				
			|||||||
    shippingProductModal: ShippingProductModal,
 | 
					    shippingProductModal: ShippingProductModal,
 | 
				
			||||||
    departmentModal: DepartmentModal,
 | 
					    departmentModal: DepartmentModal,
 | 
				
			||||||
    addUserToDepartmentModal: AddUserToDepartmentModal,
 | 
					    addUserToDepartmentModal: AddUserToDepartmentModal,
 | 
				
			||||||
 | 
					    assignUserModal: AssignUserModal,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ type DealPageContextState = {
 | 
				
			|||||||
    selectedDeal?: DealSchema;
 | 
					    selectedDeal?: DealSchema;
 | 
				
			||||||
    setSelectedDeal: (deal: DealSchema | undefined) => void;
 | 
					    setSelectedDeal: (deal: DealSchema | undefined) => void;
 | 
				
			||||||
    refetchDeals: () => Promise<void>;
 | 
					    refetchDeals: () => Promise<void>;
 | 
				
			||||||
 | 
					    refetchDeal: () => void;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DealPageContext = createContext<DealPageContextState | undefined>(
 | 
					const DealPageContext = createContext<DealPageContextState | undefined>(
 | 
				
			||||||
@@ -22,18 +23,24 @@ const useDealPageContextState = (props: DealPageContextStateProps) => {
 | 
				
			|||||||
        undefined,
 | 
					        undefined,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => {
 | 
					    const refetchDeal = () => {
 | 
				
			||||||
        if (!defaultDealId)
 | 
					        const dealId = selectedDeal?.id ?? defaultDealId;
 | 
				
			||||||
            return;
 | 
					        if (!dealId) return;
 | 
				
			||||||
        DealService.getDealById({ dealId: defaultDealId }).then(deal => {
 | 
					 | 
				
			||||||
            setSelectedDeal(deal);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DealService.getDealById({ dealId }).then(deal => {
 | 
				
			||||||
 | 
					            setSelectedDeal(deal);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        refetchDeal();
 | 
				
			||||||
    }, []);
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        selectedDeal,
 | 
					        selectedDeal,
 | 
				
			||||||
        setSelectedDeal,
 | 
					        setSelectedDeal,
 | 
				
			||||||
        refetchDeals,
 | 
					        refetchDeals,
 | 
				
			||||||
 | 
					        refetchDeal,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,282 +1,14 @@
 | 
				
			|||||||
import { Box, Drawer, rem, Tabs } from "@mantine/core";
 | 
					import { Box, Drawer, rem, Tabs } from "@mantine/core";
 | 
				
			||||||
import { FC, useEffect } from "react";
 | 
					import { FC, ReactNode, useEffect } from "react";
 | 
				
			||||||
import { useDealPageContext } from "../../contexts/DealPageContext.tsx";
 | 
					import { useDealPageContext } from "../../contexts/DealPageContext.tsx";
 | 
				
			||||||
import { IconBox, IconCalendarUser, IconCubeSend, IconSettings, IconUser } from "@tabler/icons-react";
 | 
					import { IconBox, IconCalendarUser, IconCubeSend, IconSettings, IconUser, IconUsersGroup } from "@tabler/icons-react";
 | 
				
			||||||
import DealStatusChangeTable from "../../components/DealStatusChangeTable/DealStatusChangeTable.tsx";
 | 
					import DealStatusChangeTable from "../../components/DealStatusChangeTable/DealStatusChangeTable.tsx";
 | 
				
			||||||
import DealEditDrawerGeneralTab from "./tabs/DealEditDrawerGeneralTab.tsx";
 | 
					import DealEditDrawerGeneralTab from "./tabs/DealEditDrawerGeneralTab.tsx";
 | 
				
			||||||
import { useQueryClient } from "@tanstack/react-query";
 | 
					import { useQueryClient } from "@tanstack/react-query";
 | 
				
			||||||
import ProductAndServiceTab from "../../tabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
 | 
					import ProductAndServiceTab from "../../tabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
 | 
				
			||||||
import { motion } from "framer-motion";
 | 
					import { motion } from "framer-motion";
 | 
				
			||||||
import ClientTab from "./tabs/ClientTab.tsx";
 | 
					 | 
				
			||||||
import ShippingTab from "../../tabs/ShippingTab/ShippingTab.tsx";
 | 
					import ShippingTab from "../../tabs/ShippingTab/ShippingTab.tsx";
 | 
				
			||||||
// import styles from './DealEditDrawer.module.css';
 | 
					import EmployeesTab from "../../tabs/EmployeesTab/EmployeesTab.tsx";
 | 
				
			||||||
 | 
					 | 
				
			||||||
// const useDealServicesTableState = () => {
 | 
					 | 
				
			||||||
//     const { selectedDeal, setSelectedDeal } = useDealPageContext();
 | 
					 | 
				
			||||||
//     const tableRef = useRef<BaseTableRef<DealServiceSchema>>(null);
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//     const onServiceUpdate = (service: DealServiceSchema) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         DealService.updateDealService({
 | 
					 | 
				
			||||||
//             requestBody: {
 | 
					 | 
				
			||||||
//                 dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                 service,
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         }).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) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         DealService.addDealService({
 | 
					 | 
				
			||||||
//             requestBody: {
 | 
					 | 
				
			||||||
//                 dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                 serviceId: service.service.id,
 | 
					 | 
				
			||||||
//                 quantity: service.quantity,
 | 
					 | 
				
			||||||
//                 price: service.price,
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         }).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 useDealProductTableState = () => {
 | 
					 | 
				
			||||||
//     const { selectedDeal, setSelectedDeal } = useDealPageContext();
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//     const onProductUpdate = (product: DealProductSchema) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         DealService.updateDealProduct({
 | 
					 | 
				
			||||||
//             requestBody: {
 | 
					 | 
				
			||||||
//                 dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                 product: product,
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         }).then(async ({ ok, message }) => {
 | 
					 | 
				
			||||||
//             notifications.guess(ok, { message });
 | 
					 | 
				
			||||||
//             if (!ok) return;
 | 
					 | 
				
			||||||
//             await DealService.getDealById({ dealId: selectedDeal.id }).then(
 | 
					 | 
				
			||||||
//                 setSelectedDeal,
 | 
					 | 
				
			||||||
//             );
 | 
					 | 
				
			||||||
//         });
 | 
					 | 
				
			||||||
//     };
 | 
					 | 
				
			||||||
//     const onProductDelete = (product: DealProductSchema) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         modals.openConfirmModal({
 | 
					 | 
				
			||||||
//             title: "Удаление товара",
 | 
					 | 
				
			||||||
//             children: (
 | 
					 | 
				
			||||||
//                 <>
 | 
					 | 
				
			||||||
//                     <Text>Вы уверены, что хотите удалить товар:</Text>
 | 
					 | 
				
			||||||
//                     <Text>{product.product.name}?</Text>
 | 
					 | 
				
			||||||
//                 </>
 | 
					 | 
				
			||||||
//             ),
 | 
					 | 
				
			||||||
//             onConfirm: () => {
 | 
					 | 
				
			||||||
//                 DealService.deleteDealProduct({
 | 
					 | 
				
			||||||
//                     requestBody: {
 | 
					 | 
				
			||||||
//                         dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                         productId: product.product.id,
 | 
					 | 
				
			||||||
//                     },
 | 
					 | 
				
			||||||
//                 }).then(async ({ ok, message }) => {
 | 
					 | 
				
			||||||
//                     if (!ok) {
 | 
					 | 
				
			||||||
//                         notifications.guess(ok, { message });
 | 
					 | 
				
			||||||
//                         return;
 | 
					 | 
				
			||||||
//                     }
 | 
					 | 
				
			||||||
//                     await DealService.getDealById({
 | 
					 | 
				
			||||||
//                         dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                     }).then(setSelectedDeal);
 | 
					 | 
				
			||||||
//                 });
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//             labels: {
 | 
					 | 
				
			||||||
//                 cancel: "Отмена",
 | 
					 | 
				
			||||||
//                 confirm: "Удалить",
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         });
 | 
					 | 
				
			||||||
//     };
 | 
					 | 
				
			||||||
//     const onProductCreate = (product: DealProductSchema) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         DealService.addDealProduct({
 | 
					 | 
				
			||||||
//             requestBody: {
 | 
					 | 
				
			||||||
//                 dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                 product: product,
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         }).then(async ({ ok, message }) => {
 | 
					 | 
				
			||||||
//             if (!ok) {
 | 
					 | 
				
			||||||
//                 notifications.guess(ok, { message });
 | 
					 | 
				
			||||||
//                 return;
 | 
					 | 
				
			||||||
//             }
 | 
					 | 
				
			||||||
//             await DealService.getDealById({ dealId: selectedDeal.id }).then(
 | 
					 | 
				
			||||||
//                 setSelectedDeal,
 | 
					 | 
				
			||||||
//             );
 | 
					 | 
				
			||||||
//         });
 | 
					 | 
				
			||||||
//     };
 | 
					 | 
				
			||||||
//     const onProductMultipleDelete = (items: DealProductSchema[]) => {
 | 
					 | 
				
			||||||
//         if (!selectedDeal) return;
 | 
					 | 
				
			||||||
//         modals.openConfirmModal({
 | 
					 | 
				
			||||||
//             title: "Удаление товаров",
 | 
					 | 
				
			||||||
//             children: (
 | 
					 | 
				
			||||||
//                 <>
 | 
					 | 
				
			||||||
//                     <Text>
 | 
					 | 
				
			||||||
//                         Вы уверены, что хотите удалить выбранные товары?
 | 
					 | 
				
			||||||
//                     </Text>
 | 
					 | 
				
			||||||
//                 </>
 | 
					 | 
				
			||||||
//             ),
 | 
					 | 
				
			||||||
//             onConfirm: () => {
 | 
					 | 
				
			||||||
//                 DealService.deleteMultipleDealProducts({
 | 
					 | 
				
			||||||
//                     requestBody: {
 | 
					 | 
				
			||||||
//                         dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                         productIds: items.map(item => item.product.id),
 | 
					 | 
				
			||||||
//                     },
 | 
					 | 
				
			||||||
//                 }).then(async ({ ok, message }) => {
 | 
					 | 
				
			||||||
//                     if (!ok) {
 | 
					 | 
				
			||||||
//                         notifications.guess(ok, { message });
 | 
					 | 
				
			||||||
//                         return;
 | 
					 | 
				
			||||||
//                     }
 | 
					 | 
				
			||||||
//                     await DealService.getDealById({
 | 
					 | 
				
			||||||
//                         dealId: selectedDeal.id,
 | 
					 | 
				
			||||||
//                     }).then(setSelectedDeal);
 | 
					 | 
				
			||||||
//                 });
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//             labels: {
 | 
					 | 
				
			||||||
//                 cancel: "Отмена",
 | 
					 | 
				
			||||||
//                 confirm: "Удалить",
 | 
					 | 
				
			||||||
//             },
 | 
					 | 
				
			||||||
//         });
 | 
					 | 
				
			||||||
//     };
 | 
					 | 
				
			||||||
//     return {
 | 
					 | 
				
			||||||
//         clientId: selectedDeal?.clientId || -1,
 | 
					 | 
				
			||||||
//         products: selectedDeal?.products || [],
 | 
					 | 
				
			||||||
//         onProductUpdate,
 | 
					 | 
				
			||||||
//         onProductDelete,
 | 
					 | 
				
			||||||
//         onProductCreate,
 | 
					 | 
				
			||||||
//         onProductMultipleDelete,
 | 
					 | 
				
			||||||
//     };
 | 
					 | 
				
			||||||
// };
 | 
					 | 
				
			||||||
// const DealEditDrawerProductsTable = () => {
 | 
					 | 
				
			||||||
//     const {
 | 
					 | 
				
			||||||
//         products,
 | 
					 | 
				
			||||||
//         clientId,
 | 
					 | 
				
			||||||
//         onProductUpdate,
 | 
					 | 
				
			||||||
//         onProductDelete,
 | 
					 | 
				
			||||||
//         onProductCreate,
 | 
					 | 
				
			||||||
//         onProductMultipleDelete,
 | 
					 | 
				
			||||||
//     } = useDealProductTableState();
 | 
					 | 
				
			||||||
//     return (
 | 
					 | 
				
			||||||
//         <DealProductsTable
 | 
					 | 
				
			||||||
//             clientId={clientId}
 | 
					 | 
				
			||||||
//             items={products}
 | 
					 | 
				
			||||||
//             onChange={onProductUpdate}
 | 
					 | 
				
			||||||
//             onMultipleDelete={onProductMultipleDelete}
 | 
					 | 
				
			||||||
//             onDelete={onProductDelete}
 | 
					 | 
				
			||||||
//             onCreate={onProductCreate}
 | 
					 | 
				
			||||||
//         />
 | 
					 | 
				
			||||||
//     );
 | 
					 | 
				
			||||||
// };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useDealStatusChangeState = () => {
 | 
					const useDealStatusChangeState = () => {
 | 
				
			||||||
    const { selectedDeal } = useDealPageContext();
 | 
					    const { selectedDeal } = useDealPageContext();
 | 
				
			||||||
@@ -306,6 +38,25 @@ const DealEditDrawer: FC = () => {
 | 
				
			|||||||
        if (isVisible) return;
 | 
					        if (isVisible) return;
 | 
				
			||||||
        queryClient.invalidateQueries({ queryKey: ["getDealSummaries"] });
 | 
					        queryClient.invalidateQueries({ queryKey: ["getDealSummaries"] });
 | 
				
			||||||
    }, [isVisible]);
 | 
					    }, [isVisible]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const getTabPanel = (value: string, component: ReactNode) => {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Tabs.Panel value={value}>
 | 
				
			||||||
 | 
					                <motion.div
 | 
				
			||||||
 | 
					                    initial={{ opacity: 0 }}
 | 
				
			||||||
 | 
					                    animate={{ opacity: 1 }}
 | 
				
			||||||
 | 
					                    transition={{ duration: 0.2 }}>
 | 
				
			||||||
 | 
					                    <Box
 | 
				
			||||||
 | 
					                        h={"100%"}
 | 
				
			||||||
 | 
					                        w={"100%"}
 | 
				
			||||||
 | 
					                        p={rem(10)}>
 | 
				
			||||||
 | 
					                        {component}
 | 
				
			||||||
 | 
					                    </Box>
 | 
				
			||||||
 | 
					                </motion.div>
 | 
				
			||||||
 | 
					            </Tabs.Panel>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Drawer
 | 
					        <Drawer
 | 
				
			||||||
            size={"calc(100vw - 150px)"}
 | 
					            size={"calc(100vw - 150px)"}
 | 
				
			||||||
@@ -354,60 +105,18 @@ const DealEditDrawer: FC = () => {
 | 
				
			|||||||
                        leftSection={<IconCubeSend />}>
 | 
					                        leftSection={<IconCubeSend />}>
 | 
				
			||||||
                        Отгрузка
 | 
					                        Отгрузка
 | 
				
			||||||
                    </Tabs.Tab>
 | 
					                    </Tabs.Tab>
 | 
				
			||||||
 | 
					                    <Tabs.Tab
 | 
				
			||||||
 | 
					                        value={"employees"}
 | 
				
			||||||
 | 
					                        leftSection={<IconUsersGroup />}>
 | 
				
			||||||
 | 
					                        Исполнители
 | 
				
			||||||
 | 
					                    </Tabs.Tab>
 | 
				
			||||||
                </Tabs.List>
 | 
					                </Tabs.List>
 | 
				
			||||||
                <Tabs.Panel value={"general"}>
 | 
					                {getTabPanel("general", <DealEditDrawerGeneralTab />)}
 | 
				
			||||||
                    <motion.div
 | 
					                {getTabPanel("client", <DealEditDrawerStatusChangeTable />)}
 | 
				
			||||||
                        initial={{ opacity: 0 }}
 | 
					                {getTabPanel("history", <DealEditDrawerStatusChangeTable />)}
 | 
				
			||||||
                        animate={{ opacity: 1 }}
 | 
					                {getTabPanel("servicesAndProducts", <ProductAndServiceTab />)}
 | 
				
			||||||
                        transition={{ duration: 0.2 }}>
 | 
					                {getTabPanel("shipment", <ShippingTab />)}
 | 
				
			||||||
                        <Box
 | 
					                {getTabPanel("employees", <EmployeesTab />)}
 | 
				
			||||||
                            h={"100%"}
 | 
					 | 
				
			||||||
                            w={"100%"}
 | 
					 | 
				
			||||||
                            p={rem(10)}>
 | 
					 | 
				
			||||||
                            <DealEditDrawerGeneralTab />
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                    </motion.div>
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					 | 
				
			||||||
                <Tabs.Panel value={"client"}>
 | 
					 | 
				
			||||||
                    <motion.div
 | 
					 | 
				
			||||||
                        initial={{ opacity: 0 }}
 | 
					 | 
				
			||||||
                        animate={{ opacity: 1 }}
 | 
					 | 
				
			||||||
                        transition={{ duration: 0.2 }}>
 | 
					 | 
				
			||||||
                        <Box p={rem(10)}>
 | 
					 | 
				
			||||||
                            <ClientTab />
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                    </motion.div>
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					 | 
				
			||||||
                <Tabs.Panel value={"history"}>
 | 
					 | 
				
			||||||
                    <motion.div
 | 
					 | 
				
			||||||
                        initial={{ opacity: 0 }}
 | 
					 | 
				
			||||||
                        animate={{ opacity: 1 }}
 | 
					 | 
				
			||||||
                        transition={{ duration: 0.2 }}>
 | 
					 | 
				
			||||||
                        <Box p={rem(10)}>
 | 
					 | 
				
			||||||
                            <DealEditDrawerStatusChangeTable />
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                    </motion.div>
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					 | 
				
			||||||
                <Tabs.Panel value={"servicesAndProducts"}>
 | 
					 | 
				
			||||||
                    <motion.div
 | 
					 | 
				
			||||||
                        initial={{ opacity: 0 }}
 | 
					 | 
				
			||||||
                        animate={{ opacity: 1 }}
 | 
					 | 
				
			||||||
                        transition={{ duration: 0.2 }}>
 | 
					 | 
				
			||||||
                        <Box p={rem(10)}>
 | 
					 | 
				
			||||||
                            <ProductAndServiceTab />
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                    </motion.div>
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					 | 
				
			||||||
                <Tabs.Panel value={"shipment"}>
 | 
					 | 
				
			||||||
                    <motion.div
 | 
					 | 
				
			||||||
                        initial={{ opacity: 0 }}
 | 
					 | 
				
			||||||
                        animate={{ opacity: 1 }}
 | 
					 | 
				
			||||||
                        transition={{ duration: 0.2 }}>
 | 
					 | 
				
			||||||
                        <Box p={rem(10)}>
 | 
					 | 
				
			||||||
                            <ShippingTab />
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                    </motion.div>
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					 | 
				
			||||||
            </Tabs>
 | 
					            </Tabs>
 | 
				
			||||||
        </Drawer>
 | 
					        </Drawer>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/pages/LeadsPage/tabs/EmployeesTab/EmployeesTab.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/pages/LeadsPage/tabs/EmployeesTab/EmployeesTab.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { Stack } from "@mantine/core";
 | 
				
			||||||
 | 
					import EmployeeInput from "./components/EmployeeInput.tsx";
 | 
				
			||||||
 | 
					import EmployeesTable from "./components/EmployeesTable.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EmployeesTab = () => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Stack>
 | 
				
			||||||
 | 
					            <EmployeeInput />
 | 
				
			||||||
 | 
					            <EmployeesTable />
 | 
				
			||||||
 | 
					        </Stack>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default EmployeesTab;
 | 
				
			||||||
@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import { FC } from "react";
 | 
				
			||||||
 | 
					import ObjectSelect, { ObjectSelectProps } from "../../../../../components/ObjectSelect/ObjectSelect.tsx";
 | 
				
			||||||
 | 
					import { UserSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import useAvailableEmployeesList from "../hooks/useAvailableEmployeesList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DealData = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = DealData & Omit<
 | 
				
			||||||
 | 
					    ObjectSelectProps<UserSchema | null>,
 | 
				
			||||||
 | 
					    "data" | "getValueFn" | "getLabelFn"
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UserForDepartmentSelect: FC<Props> = ({ dealId, ...selectProps }) => {
 | 
				
			||||||
 | 
					    const { objects: employees } = useAvailableEmployeesList({ dealId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ObjectSelect
 | 
				
			||||||
 | 
					            data={employees}
 | 
				
			||||||
 | 
					            getLabelFn={(user: UserSchema) => `${user.firstName} ${user.secondName}`}
 | 
				
			||||||
 | 
					            getValueFn={(user: UserSchema) => user.id.toString()}
 | 
				
			||||||
 | 
					            {...selectProps}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					export default UserForDepartmentSelect;
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import { Button, Group } from "@mantine/core";
 | 
				
			||||||
 | 
					import { IconQrcode, IconTablePlus } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import useEmployeesTab from "../hooks/useEmployeesTab.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EmployeeInput = () => {
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					        onAssignEmployeeByQrClick,
 | 
				
			||||||
 | 
					        onAssignEmployeeManuallyClick,
 | 
				
			||||||
 | 
					    } = useEmployeesTab();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Group>
 | 
				
			||||||
 | 
					            <Button variant={"default"} onClick={onAssignEmployeeByQrClick}>
 | 
				
			||||||
 | 
					                <Group gap={"md"}>
 | 
				
			||||||
 | 
					                    <IconQrcode />
 | 
				
			||||||
 | 
					                    Добавить исполнителя по QR коду
 | 
				
			||||||
 | 
					                </Group>
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					            <Button variant={"default"} onClick={onAssignEmployeeManuallyClick}>
 | 
				
			||||||
 | 
					                <Group gap={"md"}>
 | 
				
			||||||
 | 
					                    <IconTablePlus />
 | 
				
			||||||
 | 
					                    Добавить исполнителя вручную
 | 
				
			||||||
 | 
					                </Group>
 | 
				
			||||||
 | 
					            </Button>
 | 
				
			||||||
 | 
					        </Group>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default EmployeeInput;
 | 
				
			||||||
@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
 | 
				
			||||||
 | 
					import useEmployeeTableColumns from "../hooks/useEmployeesTableColumns.tsx";
 | 
				
			||||||
 | 
					import { ActionIcon, Flex, Tooltip } from "@mantine/core";
 | 
				
			||||||
 | 
					import { IconTrash } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import { MRT_TableOptions } from "mantine-react-table";
 | 
				
			||||||
 | 
					import { AssignmentSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import useEmployeesTab from "../hooks/useEmployeesTab.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EmployeesTable = () => {
 | 
				
			||||||
 | 
					    const { selectedDeal: deal } = useDealPageContext();
 | 
				
			||||||
 | 
					    const columns = useEmployeeTableColumns();
 | 
				
			||||||
 | 
					    const { onUnassignEmployeeClick } = useEmployeesTab();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BaseTable
 | 
				
			||||||
 | 
					            data={deal?.assignments}
 | 
				
			||||||
 | 
					            columns={columns}
 | 
				
			||||||
 | 
					            restProps={
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    enableSorting: false,
 | 
				
			||||||
 | 
					                    enableColumnActions: false,
 | 
				
			||||||
 | 
					                    enableRowActions: true,
 | 
				
			||||||
 | 
					                    renderRowActions: ({ row }) => (
 | 
				
			||||||
 | 
					                        <Flex gap="md">
 | 
				
			||||||
 | 
					                            <Tooltip label="Удалить">
 | 
				
			||||||
 | 
					                                <ActionIcon
 | 
				
			||||||
 | 
					                                    onClick={() => onUnassignEmployeeClick(row.original)}
 | 
				
			||||||
 | 
					                                    variant={"default"}>
 | 
				
			||||||
 | 
					                                    <IconTrash />
 | 
				
			||||||
 | 
					                                </ActionIcon>
 | 
				
			||||||
 | 
					                            </Tooltip>
 | 
				
			||||||
 | 
					                        </Flex>
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                } as MRT_TableOptions<AssignmentSchema>
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default EmployeesTable;
 | 
				
			||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					import { DealService } from "../../../../../client";
 | 
				
			||||||
 | 
					import ObjectList from "../../../../../hooks/objectList.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useAvailableEmployeesList = ({ dealId }: Props) =>
 | 
				
			||||||
 | 
					    ObjectList({
 | 
				
			||||||
 | 
					        queryFn: () => DealService.getAvailableEmployeesToAssign({ dealId }),
 | 
				
			||||||
 | 
					        getObjectsFn: response => response.employees,
 | 
				
			||||||
 | 
					        queryKey: "getAvailableEmployeesToAssign",
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default useAvailableEmployeesList;
 | 
				
			||||||
@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					import { notifications } from "../../../../../shared/lib/notifications.ts";
 | 
				
			||||||
 | 
					import { modals } from "@mantine/modals";
 | 
				
			||||||
 | 
					import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
 | 
				
			||||||
 | 
					import { AssignmentSchema, DealService } from "../../../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useEmployeesTab = () => {
 | 
				
			||||||
 | 
					    const { selectedDeal: deal, refetchDeal } = useDealPageContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const manageEmployee = (dealId: number, userId: number, isAssign: boolean) => {
 | 
				
			||||||
 | 
					        DealService.manageEmployee({
 | 
				
			||||||
 | 
					            requestBody: {
 | 
				
			||||||
 | 
					                dealId,
 | 
				
			||||||
 | 
					                userId,
 | 
				
			||||||
 | 
					                isAssign,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					            .then(({ ok, message }) => {
 | 
				
			||||||
 | 
					                notifications.guess(ok, { message });
 | 
				
			||||||
 | 
					                refetchDeal();
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch((err) => console.log(err));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onInputFinish = (userIdInput: string) => {
 | 
				
			||||||
 | 
					        const userId = parseInt(userIdInput);
 | 
				
			||||||
 | 
					        if (isNaN(userId)) {
 | 
				
			||||||
 | 
					            notifications.error({ message: "Ошибка, некорректные данные в QR-коде" });
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!deal) return;
 | 
				
			||||||
 | 
					        manageEmployee(deal.id, userId, true);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onAssignEmployeeByQrClick = () => {
 | 
				
			||||||
 | 
					        modals.openContextModal({
 | 
				
			||||||
 | 
					            modal: "scanningModal",
 | 
				
			||||||
 | 
					            innerProps: {
 | 
				
			||||||
 | 
					                label: "Отсканируйте QR-код",
 | 
				
			||||||
 | 
					                onScan: onInputFinish,
 | 
				
			||||||
 | 
					                closeOnScan: true,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            withCloseButton: false,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onUnassignEmployeeClick = (assignment: AssignmentSchema) => {
 | 
				
			||||||
 | 
					        if (!deal) return;
 | 
				
			||||||
 | 
					        manageEmployee(deal.id, assignment.user.id, false);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onAssignEmployeeManuallyClick = () => {
 | 
				
			||||||
 | 
					        if (!deal) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        modals.openContextModal({
 | 
				
			||||||
 | 
					            modal: "assignUserModal",
 | 
				
			||||||
 | 
					            title: `Назначение исполнителя`,
 | 
				
			||||||
 | 
					            withCloseButton: false,
 | 
				
			||||||
 | 
					            innerProps: {
 | 
				
			||||||
 | 
					                deal,
 | 
				
			||||||
 | 
					                manageEmployee,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        onAssignEmployeeByQrClick,
 | 
				
			||||||
 | 
					        onAssignEmployeeManuallyClick,
 | 
				
			||||||
 | 
					        onUnassignEmployeeClick,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default useEmployeesTab;
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					import { useMemo } from "react";
 | 
				
			||||||
 | 
					import { MRT_ColumnDef } from "mantine-react-table";
 | 
				
			||||||
 | 
					import { AssignmentSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useEmployeeTableColumns = () => {
 | 
				
			||||||
 | 
					    return useMemo<MRT_ColumnDef<AssignmentSchema>[]>(
 | 
				
			||||||
 | 
					        () => [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "createdAt",
 | 
				
			||||||
 | 
					                header: "Дата назначения",
 | 
				
			||||||
 | 
					                Cell: ({ cell }) => new Date(cell.getValue() as string).toLocaleString("ru"),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                header: "ФИО",
 | 
				
			||||||
 | 
					                Cell: ({ row }) =>
 | 
				
			||||||
 | 
					                    `${row.original.user.secondName} ${row.original.user.firstName} ${row.original.user.patronymic}`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "user.role.name",
 | 
				
			||||||
 | 
					                header: "Роль",
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "user.position.name",
 | 
				
			||||||
 | 
					                header: "Должность",
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                accessorKey: "user.comment",
 | 
				
			||||||
 | 
					                header: "Дополнительная информация",
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default useEmployeeTableColumns;
 | 
				
			||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					import { useForm } from "@mantine/form";
 | 
				
			||||||
 | 
					import { ContextModalProps } from "@mantine/modals";
 | 
				
			||||||
 | 
					import { Button, Flex, rem } from "@mantine/core";
 | 
				
			||||||
 | 
					import { DealSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					import AssignUserModalForm from "../types/AssignUserModalForm.tsx";
 | 
				
			||||||
 | 
					import AvailableEmployeesSelect from "../components/AvailableEmployeesSelect.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    deal: DealSchema;
 | 
				
			||||||
 | 
					    manageEmployee: (dealId: number, userId: number, isAssign: boolean) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssignEmployeeModal = ({
 | 
				
			||||||
 | 
					                                 context,
 | 
				
			||||||
 | 
					                                 id,
 | 
				
			||||||
 | 
					                                 innerProps,
 | 
				
			||||||
 | 
					                             }: ContextModalProps<Props>) => {
 | 
				
			||||||
 | 
					    const {
 | 
				
			||||||
 | 
					        deal,
 | 
				
			||||||
 | 
					        manageEmployee,
 | 
				
			||||||
 | 
					    } = innerProps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const form = useForm<Partial<AssignUserModalForm>>({
 | 
				
			||||||
 | 
					        validate: {
 | 
				
			||||||
 | 
					            employee: employee => !employee && "Необходимо выбрать работника",
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onSubmit = () => {
 | 
				
			||||||
 | 
					        if (!form.values.employee) return;
 | 
				
			||||||
 | 
					        manageEmployee(deal.id, form.values.employee.id, true);
 | 
				
			||||||
 | 
					        context.closeContextModal(id);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <form onSubmit={form.onSubmit(() => onSubmit())}>
 | 
				
			||||||
 | 
					            <Flex
 | 
				
			||||||
 | 
					                direction={"column"}
 | 
				
			||||||
 | 
					                gap={rem(10)}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                <AvailableEmployeesSelect
 | 
				
			||||||
 | 
					                    label={"Работник"}
 | 
				
			||||||
 | 
					                    placeholder={"Выберите работника"}
 | 
				
			||||||
 | 
					                    {...form.getInputProps("employee")}
 | 
				
			||||||
 | 
					                    dealId={deal.id}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					                <Button
 | 
				
			||||||
 | 
					                    variant={"default"}
 | 
				
			||||||
 | 
					                    type={"submit"}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    Сохранить
 | 
				
			||||||
 | 
					                </Button>
 | 
				
			||||||
 | 
					            </Flex>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AssignEmployeeModal;
 | 
				
			||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import { UserSchema } from "../../../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AssignUserModalForm = {
 | 
				
			||||||
 | 
					    employee: UserSchema;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AssignUserModalForm;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user