feat: deal product services
This commit is contained in:
		@@ -70,8 +70,12 @@ export type { DealUpdateGeneralInfoRequest } from './models/DealUpdateGeneralInf
 | 
				
			|||||||
export type { DealUpdateGeneralInfoResponse } from './models/DealUpdateGeneralInfoResponse';
 | 
					export type { DealUpdateGeneralInfoResponse } from './models/DealUpdateGeneralInfoResponse';
 | 
				
			||||||
export type { DealUpdateProductQuantityRequest } from './models/DealUpdateProductQuantityRequest';
 | 
					export type { DealUpdateProductQuantityRequest } from './models/DealUpdateProductQuantityRequest';
 | 
				
			||||||
export type { DealUpdateProductQuantityResponse } from './models/DealUpdateProductQuantityResponse';
 | 
					export type { DealUpdateProductQuantityResponse } from './models/DealUpdateProductQuantityResponse';
 | 
				
			||||||
 | 
					export type { DealUpdateProductRequest } from './models/DealUpdateProductRequest';
 | 
				
			||||||
 | 
					export type { DealUpdateProductResponse } from './models/DealUpdateProductResponse';
 | 
				
			||||||
export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest';
 | 
					export type { DealUpdateServiceQuantityRequest } from './models/DealUpdateServiceQuantityRequest';
 | 
				
			||||||
export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse';
 | 
					export type { DealUpdateServiceQuantityResponse } from './models/DealUpdateServiceQuantityResponse';
 | 
				
			||||||
 | 
					export type { DealUpdateServiceRequest } from './models/DealUpdateServiceRequest';
 | 
				
			||||||
 | 
					export type { DealUpdateServiceResponse } from './models/DealUpdateServiceResponse';
 | 
				
			||||||
export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
 | 
					export type { GetAllBarcodeTemplateAttributesResponse } from './models/GetAllBarcodeTemplateAttributesResponse';
 | 
				
			||||||
export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse';
 | 
					export type { GetAllBarcodeTemplateSizesResponse } from './models/GetAllBarcodeTemplateSizesResponse';
 | 
				
			||||||
export type { GetAllBarcodeTemplatesResponse } from './models/GetAllBarcodeTemplatesResponse';
 | 
					export type { GetAllBarcodeTemplatesResponse } from './models/GetAllBarcodeTemplatesResponse';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,5 +6,6 @@ export type DealAddServiceRequest = {
 | 
				
			|||||||
    dealId: number;
 | 
					    dealId: number;
 | 
				
			||||||
    serviceId: number;
 | 
					    serviceId: number;
 | 
				
			||||||
    quantity: number;
 | 
					    quantity: number;
 | 
				
			||||||
 | 
					    price: number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/client/models/DealUpdateProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealUpdateProductRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { DealProductSchema } from './DealProductSchema';
 | 
				
			||||||
 | 
					export type DealUpdateProductRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    product: DealProductSchema;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealUpdateProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealUpdateProductResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealUpdateProductResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/models/DealUpdateServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/models/DealUpdateServiceRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { DealServiceSchema } from './DealServiceSchema';
 | 
				
			||||||
 | 
					export type DealUpdateServiceRequest = {
 | 
				
			||||||
 | 
					    dealId: number;
 | 
				
			||||||
 | 
					    service: DealServiceSchema;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/models/DealUpdateServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/DealUpdateServiceResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type DealUpdateServiceResponse = {
 | 
				
			||||||
 | 
					    ok: boolean;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,8 +31,12 @@ import type { DealUpdateGeneralInfoRequest } from '../models/DealUpdateGeneralIn
 | 
				
			|||||||
import type { DealUpdateGeneralInfoResponse } from '../models/DealUpdateGeneralInfoResponse';
 | 
					import type { DealUpdateGeneralInfoResponse } from '../models/DealUpdateGeneralInfoResponse';
 | 
				
			||||||
import type { DealUpdateProductQuantityRequest } from '../models/DealUpdateProductQuantityRequest';
 | 
					import type { DealUpdateProductQuantityRequest } from '../models/DealUpdateProductQuantityRequest';
 | 
				
			||||||
import type { DealUpdateProductQuantityResponse } from '../models/DealUpdateProductQuantityResponse';
 | 
					import type { DealUpdateProductQuantityResponse } from '../models/DealUpdateProductQuantityResponse';
 | 
				
			||||||
 | 
					import type { DealUpdateProductRequest } from '../models/DealUpdateProductRequest';
 | 
				
			||||||
 | 
					import type { DealUpdateProductResponse } from '../models/DealUpdateProductResponse';
 | 
				
			||||||
import type { DealUpdateServiceQuantityRequest } from '../models/DealUpdateServiceQuantityRequest';
 | 
					import type { DealUpdateServiceQuantityRequest } from '../models/DealUpdateServiceQuantityRequest';
 | 
				
			||||||
import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
					import type { DealUpdateServiceQuantityResponse } from '../models/DealUpdateServiceQuantityResponse';
 | 
				
			||||||
 | 
					import type { DealUpdateServiceRequest } from '../models/DealUpdateServiceRequest';
 | 
				
			||||||
 | 
					import type { DealUpdateServiceResponse } from '../models/DealUpdateServiceResponse';
 | 
				
			||||||
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';
 | 
				
			||||||
@@ -241,7 +245,7 @@ export class DealService {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Services Update
 | 
					     * Services Update Quantity
 | 
				
			||||||
     * @returns DealUpdateServiceQuantityResponse Successful Response
 | 
					     * @returns DealUpdateServiceQuantityResponse Successful Response
 | 
				
			||||||
     * @throws ApiError
 | 
					     * @throws ApiError
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -260,6 +264,26 @@ export class DealService {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Services Update
 | 
				
			||||||
 | 
					     * @returns DealUpdateServiceResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static updateDealService({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealUpdateServiceRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealUpdateServiceResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/services/update',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Services Delete
 | 
					     * Services Delete
 | 
				
			||||||
     * @returns DealDeleteServiceResponse Successful Response
 | 
					     * @returns DealDeleteServiceResponse Successful Response
 | 
				
			||||||
@@ -380,4 +404,24 @@ export class DealService {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Products Update
 | 
				
			||||||
 | 
					     * @returns DealUpdateProductResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static updateDealProduct({
 | 
				
			||||||
 | 
					        requestBody,
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					        requestBody: DealUpdateProductRequest,
 | 
				
			||||||
 | 
					    }): CancelablePromise<DealUpdateProductResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'POST',
 | 
				
			||||||
 | 
					            url: '/deal/product/update',
 | 
				
			||||||
 | 
					            body: requestBody,
 | 
				
			||||||
 | 
					            mediaType: 'application/json',
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                422: `Validation Error`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,8 @@ const DealSummaryCard: FC<Props> = ({dealSummary}) => {
 | 
				
			|||||||
        const currentDate = new Date();
 | 
					        const currentDate = new Date();
 | 
				
			||||||
        const diff = deadlineDate.getTime() - currentDate.getTime();
 | 
					        const diff = deadlineDate.getTime() - currentDate.getTime();
 | 
				
			||||||
        const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
 | 
					        const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
 | 
				
			||||||
 | 
					        if (diffDays < 0)
 | 
				
			||||||
 | 
					            return 'grey.8'; // for past deadlines
 | 
				
			||||||
        if (diffDays === 1) {
 | 
					        if (diffDays === 1) {
 | 
				
			||||||
            return 'yellow.8';
 | 
					            return 'yellow.8';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import {Select, SelectProps} from "@mantine/core";
 | 
					import {Select, SelectProps} from "@mantine/core";
 | 
				
			||||||
import {useEffect, useMemo, useState} from "react";
 | 
					import {useEffect, useMemo, useState} from "react";
 | 
				
			||||||
import {ObjectWithNameAndId} from "../../types/utils.ts";
 | 
					import {ObjectWithNameAndId} from "../../types/utils.ts";
 | 
				
			||||||
import {groupBy} from "lodash";
 | 
					import {groupBy, omit} from "lodash";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type SelectObjectType<T extends ObjectWithNameAndId> = T;
 | 
					export type SelectObjectType<T extends ObjectWithNameAndId> = T;
 | 
				
			||||||
@@ -16,6 +16,7 @@ type RestProps<T extends ObjectWithNameAndId> = {
 | 
				
			|||||||
    onChange: (value: SelectObjectType<T>) => void;
 | 
					    onChange: (value: SelectObjectType<T>) => void;
 | 
				
			||||||
    data: SelectObjectType<T>[];
 | 
					    data: SelectObjectType<T>[];
 | 
				
			||||||
    groupBy?: (item: SelectObjectType<T>) => string;
 | 
					    groupBy?: (item: SelectObjectType<T>) => string;
 | 
				
			||||||
 | 
					    filterBy?: (item: SelectObjectType<T>) => boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ObjectSelectProps<T extends ObjectWithNameAndId> =
 | 
					export type ObjectSelectProps<T extends ObjectWithNameAndId> =
 | 
				
			||||||
@@ -30,8 +31,10 @@ const ObjectSelect = <T extends ObjectWithNameAndId, >(props: ObjectSelectProps<
 | 
				
			|||||||
    const value = isControlled ? props.value : internalValue;
 | 
					    const value = isControlled ? props.value : internalValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const data = useMemo(() => {
 | 
					    const data = useMemo(() => {
 | 
				
			||||||
 | 
					        const propsData = props.filterBy ? props.data.filter(props.filterBy) : props.data;
 | 
				
			||||||
        if (props.groupBy) {
 | 
					        if (props.groupBy) {
 | 
				
			||||||
            const groupedData = groupBy(props.data, props.groupBy);
 | 
					
 | 
				
			||||||
 | 
					            const groupedData = groupBy(propsData, props.groupBy);
 | 
				
			||||||
            return Object.entries(groupedData).map(([group, items]) => ({
 | 
					            return Object.entries(groupedData).map(([group, items]) => ({
 | 
				
			||||||
                group,
 | 
					                group,
 | 
				
			||||||
                items: items.map(item => ({
 | 
					                items: items.map(item => ({
 | 
				
			||||||
@@ -40,7 +43,7 @@ const ObjectSelect = <T extends ObjectWithNameAndId, >(props: ObjectSelectProps<
 | 
				
			|||||||
                }))
 | 
					                }))
 | 
				
			||||||
            }));
 | 
					            }));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return props.data.map(item => ({
 | 
					            return propsData.map(item => ({
 | 
				
			||||||
                label: item.name,
 | 
					                label: item.name,
 | 
				
			||||||
                value: item.id.toString()
 | 
					                value: item.id.toString()
 | 
				
			||||||
            }));
 | 
					            }));
 | 
				
			||||||
@@ -62,10 +65,10 @@ const ObjectSelect = <T extends ObjectWithNameAndId, >(props: ObjectSelectProps<
 | 
				
			|||||||
        if (isControlled || !internalValue) return;
 | 
					        if (isControlled || !internalValue) return;
 | 
				
			||||||
        props.onChange(internalValue);
 | 
					        props.onChange(internalValue);
 | 
				
			||||||
    }, [internalValue]);
 | 
					    }, [internalValue]);
 | 
				
			||||||
 | 
					    const restProps = omit(props, ['filterBy', 'groupBy']);
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Select
 | 
					        <Select
 | 
				
			||||||
            {...props}
 | 
					            {...restProps}
 | 
				
			||||||
            value={value?.id.toString()}
 | 
					            value={value?.id.toString()}
 | 
				
			||||||
            onChange={handleOnChange}
 | 
					            onChange={handleOnChange}
 | 
				
			||||||
            data={data}
 | 
					            data={data}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
import {ProductSchema} from "../../client";
 | 
					import {ProductSchema} from "../../client";
 | 
				
			||||||
import {Select, SelectProps} from "@mantine/core";
 | 
					import {FC} from "react";
 | 
				
			||||||
import {FC, useEffect, useMemo, useState} from "react";
 | 
					 | 
				
			||||||
import useProductsList from "../../pages/ProductsPage/hooks/useProductsList.tsx";
 | 
					import useProductsList from "../../pages/ProductsPage/hooks/useProductsList.tsx";
 | 
				
			||||||
import {omit} from "lodash";
 | 
					import {omit} from "lodash";
 | 
				
			||||||
import ObjectSelect, {ObjectSelectProps} from "../ObjectSelect/ObjectSelect.tsx";
 | 
					import ObjectSelect, {ObjectSelectProps} from "../ObjectSelect/ObjectSelect.tsx";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,27 +1,37 @@
 | 
				
			|||||||
import {ObjectSelectProps} from "../ObjectSelect/ObjectSelect.tsx";
 | 
					import {ObjectSelectProps} from "../ObjectSelect/ObjectSelect.tsx";
 | 
				
			||||||
import {ServiceSchema} from "../../client";
 | 
					import {ServiceSchema} from "../../client";
 | 
				
			||||||
import {Flex, FlexProps, NumberInput, NumberInputProps, rem} from "@mantine/core";
 | 
					import {ActionIcon, Flex, FlexProps, NumberInput, NumberInputProps, rem} from "@mantine/core";
 | 
				
			||||||
import {FC, useEffect, useState} from "react";
 | 
					import {FC, useEffect, useRef, useState} from "react";
 | 
				
			||||||
import ServiceSelectNew from "../Selects/ServiceSelectNew/ServiceSelectNew.tsx";
 | 
					import ServiceSelectNew from "../Selects/ServiceSelectNew/ServiceSelectNew.tsx";
 | 
				
			||||||
 | 
					import {ServiceType} from "../../shared/enums/ServiceType.ts";
 | 
				
			||||||
 | 
					import {IconReload, IconTrash, IconUpload} from "@tabler/icons-react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, 'data'>;
 | 
					type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, 'data'>;
 | 
				
			||||||
type PriceProps = NumberInputProps;
 | 
					type PriceProps = NumberInputProps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
    serviceProps: ServiceProps,
 | 
					    serviceProps: ServiceProps,
 | 
				
			||||||
    priceProps: PriceProps
 | 
					    priceProps: PriceProps,
 | 
				
			||||||
    quantity: number;
 | 
					    quantity: number,
 | 
				
			||||||
    containerProps: FlexProps
 | 
					    containerProps: FlexProps,
 | 
				
			||||||
 | 
					    filterType?: ServiceType
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const ServiceWithPriceInput: FC<Props> = ({serviceProps, priceProps, quantity, containerProps}) => {
 | 
					const ServiceWithPriceInput: FC<Props> = ({
 | 
				
			||||||
 | 
					                                              serviceProps,
 | 
				
			||||||
 | 
					                                              priceProps,
 | 
				
			||||||
 | 
					                                              quantity,
 | 
				
			||||||
 | 
					                                              containerProps,
 | 
				
			||||||
 | 
					                                              filterType = ServiceType.PRODUCT_SERVICE
 | 
				
			||||||
 | 
					                                          }) => {
 | 
				
			||||||
    const [price, setPrice] = useState<number | undefined>(
 | 
					    const [price, setPrice] = useState<number | undefined>(
 | 
				
			||||||
        typeof priceProps.value === 'number' ? priceProps.value : undefined);
 | 
					        typeof priceProps.value === 'number' ? priceProps.value : undefined);
 | 
				
			||||||
    const [service, setService] = useState<ServiceSchema | undefined>(serviceProps.value);
 | 
					    const [service, setService] = useState<ServiceSchema | undefined>(serviceProps.value);
 | 
				
			||||||
 | 
					    const isFirstRender = useRef(true);
 | 
				
			||||||
    const setPriceBasedOnQuantity = (): boolean => {
 | 
					    const setPriceBasedOnQuantity = (): boolean => {
 | 
				
			||||||
        if (!service || !service.priceRanges.length) return false;
 | 
					        if (!service || !service.priceRanges.length) return false;
 | 
				
			||||||
        const range = service.priceRanges.find(priceRange =>
 | 
					        const range = service.priceRanges.find(priceRange =>
 | 
				
			||||||
            quantity >= priceRange.fromQuantity && quantity <= priceRange.toQuantity) || service.priceRanges[0];
 | 
					            quantity >= priceRange.fromQuantity && quantity <= priceRange.toQuantity) || service.priceRanges[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setPrice(range.price);
 | 
					        setPrice(range.price);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -38,34 +48,56 @@ const ServiceWithPriceInput: FC<Props> = ({serviceProps, priceProps, quantity, c
 | 
				
			|||||||
        setPrice(value);
 | 
					        setPrice(value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (isFirstRender.current) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setPriceBasedOnQuantity();
 | 
					        setPriceBasedOnQuantity();
 | 
				
			||||||
    }, [quantity]);
 | 
					    }, [quantity]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        if (!priceProps.onChange || !price) return;
 | 
					        if (isFirstRender.current) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!priceProps.onChange || typeof price === 'undefined') return;
 | 
				
			||||||
        priceProps.onChange(price);
 | 
					        priceProps.onChange(price);
 | 
				
			||||||
    }, [price]);
 | 
					    }, [price]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        // if (!isFirstRender) setPrice(0);
 | 
				
			||||||
 | 
					        // if (isFirstRender.current && price) return;
 | 
				
			||||||
        if (!serviceProps.onChange || !service) return;
 | 
					        if (!serviceProps.onChange || !service) return;
 | 
				
			||||||
 | 
					        if (price && isFirstRender.current) return;
 | 
				
			||||||
        setPriceBasedOnService();
 | 
					        setPriceBasedOnService();
 | 
				
			||||||
        serviceProps.onChange(service);
 | 
					        serviceProps.onChange(service);
 | 
				
			||||||
    }, [service]);
 | 
					    }, [service]);
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        console.log('first render')
 | 
				
			||||||
 | 
					        isFirstRender.current = false;
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onReload = () => {
 | 
				
			||||||
 | 
					        setPriceBasedOnService();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Flex
 | 
					        <Flex
 | 
				
			||||||
            {...containerProps}
 | 
					            align={"center"}
 | 
				
			||||||
            gap={rem(10)}
 | 
					            gap={rem(10)}
 | 
				
			||||||
 | 
					            {...containerProps}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <ActionIcon variant={"default"}>
 | 
				
			||||||
 | 
					                <IconReload onClick={() => onReload()}/>
 | 
				
			||||||
 | 
					            </ActionIcon>
 | 
				
			||||||
            <ServiceSelectNew
 | 
					            <ServiceSelectNew
 | 
				
			||||||
                {...serviceProps}
 | 
					                {...serviceProps}
 | 
				
			||||||
                value={service}
 | 
					                value={service}
 | 
				
			||||||
                onChange={onServiceManualChange}
 | 
					                onChange={onServiceManualChange}
 | 
				
			||||||
 | 
					                filterType={filterType}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <NumberInput
 | 
					            <NumberInput
 | 
				
			||||||
                {...priceProps}
 | 
					                {...priceProps}
 | 
				
			||||||
                onChange={onPriceManualChange}
 | 
					                onChange={onPriceManualChange}
 | 
				
			||||||
                value={price}
 | 
					                value={price}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </Flex>
 | 
					        </Flex>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@ type Props = {
 | 
				
			|||||||
const BarcodeTemplateAdditionalFieldTable: FC<Props> = (props: Props) => {
 | 
					const BarcodeTemplateAdditionalFieldTable: FC<Props> = (props: Props) => {
 | 
				
			||||||
    const {value, onChange} = props;
 | 
					    const {value, onChange} = props;
 | 
				
			||||||
    const [innerValue, setInnerValue] = useState<FieldType[]>(props.value || []);
 | 
					    const [innerValue, setInnerValue] = useState<FieldType[]>(props.value || []);
 | 
				
			||||||
    console.log(innerValue);
 | 
					 | 
				
			||||||
    const onNameChange = (field: FieldType, newName: string) => {
 | 
					    const onNameChange = (field: FieldType, newName: string) => {
 | 
				
			||||||
        const newField = {...field, name: newName};
 | 
					        const newField = {...field, name: newName};
 | 
				
			||||||
        const newFields = innerValue.map(f => f === field ? newField : f);
 | 
					        const newFields = innerValue.map(f => f === field ? newField : f);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,6 @@ const BarcodeTemplateFormModal = ({
 | 
				
			|||||||
            name: (name: string | undefined) => name && name.trim() !== '' ? null : "Необходимо ввести название шаблона",
 | 
					            name: (name: string | undefined) => name && name.trim() !== '' ? null : "Необходимо ввести название шаблона",
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    console.log(form.values.additionalAttributes);
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <BaseFormModal
 | 
					        <BaseFormModal
 | 
				
			||||||
            {...innerProps}
 | 
					            {...innerProps}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import {ActionIcon, Button, Flex, Input, rem} from "@mantine/core";
 | 
					import {ActionIcon, Button, ComboboxItem, ComboboxItemGroup, Flex, Input, OptionsFilter, rem} from "@mantine/core";
 | 
				
			||||||
import {BaseFormInputProps} from "../../../../types/utils.ts";
 | 
					import {BaseFormInputProps} from "../../../../types/utils.ts";
 | 
				
			||||||
import {DealProductServiceSchema, ServiceSchema} from "../../../../client";
 | 
					import {DealProductServiceSchema, ServiceSchema} from "../../../../client";
 | 
				
			||||||
import {FC, useEffect, useState} from "react";
 | 
					import {FC, useEffect, useState} from "react";
 | 
				
			||||||
@@ -32,6 +32,16 @@ const DealProductServiceTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
        setInnerValue(oldValue => oldValue.filter((_, i) => i !== idx));
 | 
					        setInnerValue(oldValue => oldValue.filter((_, i) => i !== idx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const serviceOptionsFilter = ({options}: { options: ComboboxItemGroup[] }) => {
 | 
				
			||||||
 | 
					        const productServiceIds = innerValue.map(service => service.service?.id);
 | 
				
			||||||
 | 
					        return (options as ComboboxItemGroup[]).map(({items, group}) => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                group,
 | 
				
			||||||
 | 
					                items: items.filter(item => !productServiceIds.includes(parseInt((item as ComboboxItem).value)))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        onChange(innerValue as DealProductServiceSchema[]);
 | 
					        onChange(innerValue as DealProductServiceSchema[]);
 | 
				
			||||||
    }, [innerValue]);
 | 
					    }, [innerValue]);
 | 
				
			||||||
@@ -39,7 +49,8 @@ const DealProductServiceTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
        <Input.Wrapper error={error}>
 | 
					        <Input.Wrapper error={error}>
 | 
				
			||||||
            <Flex direction={"column"} gap={rem(10)}>
 | 
					            <Flex direction={"column"} gap={rem(10)}>
 | 
				
			||||||
                {innerValue.map((service, idx) => (
 | 
					                {innerValue.map((service, idx) => (
 | 
				
			||||||
                    <Flex key={idx} direction={"row"} gap={rem(10)} align={"center"} justify={"stretch"}>
 | 
					                    <Flex key={service.service?.name || idx} direction={"row"} gap={rem(10)} align={"center"}
 | 
				
			||||||
 | 
					                          justify={"stretch"}>
 | 
				
			||||||
                        <ActionIcon onClick={() => onDelete(idx)} variant={"default"}>
 | 
					                        <ActionIcon onClick={() => onDelete(idx)} variant={"default"}>
 | 
				
			||||||
                            <IconTrash/>
 | 
					                            <IconTrash/>
 | 
				
			||||||
                        </ActionIcon>
 | 
					                        </ActionIcon>
 | 
				
			||||||
@@ -48,7 +59,8 @@ const DealProductServiceTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
                                onChange: (event) => onServiceChange(idx, event),
 | 
					                                onChange: (event) => onServiceChange(idx, event),
 | 
				
			||||||
                                value: service.service,
 | 
					                                value: service.service,
 | 
				
			||||||
                                placeholder: "Выберите услугу",
 | 
					                                placeholder: "Выберите услугу",
 | 
				
			||||||
                                style: {width: "100%"}
 | 
					                                style: {width: "100%"},
 | 
				
			||||||
 | 
					                                filter: serviceOptionsFilter as OptionsFilter
 | 
				
			||||||
                            }}
 | 
					                            }}
 | 
				
			||||||
                            priceProps={{
 | 
					                            priceProps={{
 | 
				
			||||||
                                onChange: (event) => onQuantityChange(idx, event),
 | 
					                                onChange: (event) => onQuantityChange(idx, event),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ const DealProductsTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
                onCreate: (product) => onCreate(product as DealProductSchema),
 | 
					                onCreate: (product) => onCreate(product as DealProductSchema),
 | 
				
			||||||
                clientId
 | 
					                clientId
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            size:"lg"
 | 
					            size: "lg"
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const onPrintBarcodeClick = (product: DealProductSchema) => {
 | 
					    const onPrintBarcodeClick = (product: DealProductSchema) => {
 | 
				
			||||||
@@ -73,6 +73,7 @@ const DealProductsTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const onEditClick = (product: DealProductSchema) => {
 | 
					    const onEditClick = (product: DealProductSchema) => {
 | 
				
			||||||
 | 
					        if (!onChange) return;
 | 
				
			||||||
        modals.openContextModal({
 | 
					        modals.openContextModal({
 | 
				
			||||||
            modal: "addDealProduct",
 | 
					            modal: "addDealProduct",
 | 
				
			||||||
            title: 'Создание товара',
 | 
					            title: 'Создание товара',
 | 
				
			||||||
@@ -80,10 +81,9 @@ const DealProductsTable: FC<Props> = (props: Props) => {
 | 
				
			|||||||
            innerProps: {
 | 
					            innerProps: {
 | 
				
			||||||
                clientId: clientId,
 | 
					                clientId: clientId,
 | 
				
			||||||
                element: product,
 | 
					                element: product,
 | 
				
			||||||
                onChange: () => {
 | 
					                onChange: onChange
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            size:"lg"
 | 
					            size: "lg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
import {useMemo} from "react";
 | 
					import {useMemo} from "react";
 | 
				
			||||||
import {MRT_ColumnDef} from "mantine-react-table";
 | 
					import {MRT_ColumnDef} from "mantine-react-table";
 | 
				
			||||||
import {DealProductSchema} from "../../../../client";
 | 
					import {DealProductSchema} from "../../../../client";
 | 
				
			||||||
import PlusMinusInput from "../../../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
					 | 
				
			||||||
import {List} from "@mantine/core";
 | 
					import {List} from "@mantine/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
@@ -11,7 +10,7 @@ type Props = {
 | 
				
			|||||||
const useDealProductsTableColumns = (props: Props) => {
 | 
					const useDealProductsTableColumns = (props: Props) => {
 | 
				
			||||||
    const {onChange, data} = props;
 | 
					    const {onChange, data} = props;
 | 
				
			||||||
    const totalQuantity = useMemo(() => data.reduce((acc, row) => acc + row.quantity, 0), [data]);
 | 
					    const totalQuantity = useMemo(() => data.reduce((acc, row) => acc + row.quantity, 0), [data]);
 | 
				
			||||||
 | 
					    const totalPrice = useMemo(() => data.reduce((totalAcc, row) => totalAcc + row.services.reduce((singleAcc, service) => singleAcc + service.price * row.quantity, 0), 0), [data]);
 | 
				
			||||||
    return useMemo<MRT_ColumnDef<DealProductSchema>[]>(() => [
 | 
					    return useMemo<MRT_ColumnDef<DealProductSchema>[]>(() => [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            accessorKey: "product.article",
 | 
					            accessorKey: "product.article",
 | 
				
			||||||
@@ -50,14 +49,24 @@ const useDealProductsTableColumns = (props: Props) => {
 | 
				
			|||||||
            enableSorting: false,
 | 
					            enableSorting: false,
 | 
				
			||||||
            enableColumnActions: false,
 | 
					            enableColumnActions: false,
 | 
				
			||||||
            Footer: <>Всего товаров: {totalQuantity} </>,
 | 
					            Footer: <>Всего товаров: {totalQuantity} </>,
 | 
				
			||||||
            Cell: ({row}) => {
 | 
					        },
 | 
				
			||||||
                return (
 | 
					        {
 | 
				
			||||||
                    <PlusMinusInput
 | 
					            header: "Услуги",
 | 
				
			||||||
                        value={row.original.quantity}
 | 
					            Cell: ({row}) => <List size={"sm"}>{
 | 
				
			||||||
                        onChange={(value) => onChange(row.original, value)}
 | 
					                row.original.services.map(service => `${service.service.name} (${service.price}₽ за шт)`)
 | 
				
			||||||
                    />
 | 
					                    .map(serviceText => <List.Item key={serviceText}>
 | 
				
			||||||
                )
 | 
					                            {serviceText}
 | 
				
			||||||
            }
 | 
					                        </List.Item>
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
 | 
					            </List>,
 | 
				
			||||||
 | 
					            enableColumnActions: false,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            header: "Итоговая стоимость услуг",
 | 
				
			||||||
 | 
					            Cell: ({row}) => <>
 | 
				
			||||||
 | 
					                {row.original.services.reduce((acc, service) => acc + row.original.quantity * service.price, 0)}</>,
 | 
				
			||||||
 | 
					            enableColumnActions: false,
 | 
				
			||||||
 | 
					            Footer: <>Всего стоимость услуг: {totalPrice}</>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ], [onChange, data])
 | 
					    ], [onChange, data])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ import {CRUDTableProps} from "../../../../types/CRUDTable.tsx";
 | 
				
			|||||||
import {MRT_TableOptions} from "mantine-react-table";
 | 
					import {MRT_TableOptions} from "mantine-react-table";
 | 
				
			||||||
import {ActionIcon, Button, Flex, rem, Tooltip} from "@mantine/core";
 | 
					import {ActionIcon, Button, Flex, rem, Tooltip} from "@mantine/core";
 | 
				
			||||||
import {openContextModal} from "@mantine/modals";
 | 
					import {openContextModal} from "@mantine/modals";
 | 
				
			||||||
import {IconTrash} from "@tabler/icons-react";
 | 
					import {IconEdit, IconTrash} from "@tabler/icons-react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type RestProps = {
 | 
					type RestProps = {
 | 
				
			||||||
    onMultipleDelete?: (items: DealServiceSchema[]) => void;
 | 
					    onMultipleDelete?: (items: DealServiceSchema[]) => void;
 | 
				
			||||||
@@ -22,13 +22,15 @@ const DealServicesTable: FC<Props> = (
 | 
				
			|||||||
        onMultipleDelete,
 | 
					        onMultipleDelete,
 | 
				
			||||||
        tableRef
 | 
					        tableRef
 | 
				
			||||||
    }) => {
 | 
					    }) => {
 | 
				
			||||||
 | 
					    const serviceIds = items.map(item => item.service.id);
 | 
				
			||||||
    const onQuantityChange = (service: DealServiceSchema, quantity: number) => {
 | 
					    const onQuantityChange = (service: DealServiceSchema, quantity: number) => {
 | 
				
			||||||
        if (!onChange) return;
 | 
					 | 
				
			||||||
        if (quantity <= 0 && onDelete) {
 | 
					 | 
				
			||||||
            onDelete(service);
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
        }
 | 
					        // if (!onChange) return;
 | 
				
			||||||
        onChange({...service, quantity});
 | 
					        // if (quantity <= 0 && onDelete) {
 | 
				
			||||||
 | 
					        //     onDelete(service);
 | 
				
			||||||
 | 
					        //     return;
 | 
				
			||||||
 | 
					        // }
 | 
				
			||||||
 | 
					        // onChange({...service, quantity});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const columns = useDealServicesTableColumns({
 | 
					    const columns = useDealServicesTableColumns({
 | 
				
			||||||
        onChange: onQuantityChange,
 | 
					        onChange: onQuantityChange,
 | 
				
			||||||
@@ -40,11 +42,24 @@ const DealServicesTable: FC<Props> = (
 | 
				
			|||||||
            title: "Добавление услуги",
 | 
					            title: "Добавление услуги",
 | 
				
			||||||
            modal: "addDealService",
 | 
					            modal: "addDealService",
 | 
				
			||||||
            innerProps: {
 | 
					            innerProps: {
 | 
				
			||||||
                onCreate: (event) => onCreate(event as DealServiceSchema)
 | 
					                onCreate: (event) => onCreate(event as DealServiceSchema),
 | 
				
			||||||
 | 
					                serviceIds
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    const onEditClick = (service: DealServiceSchema) => {
 | 
				
			||||||
 | 
					        if (!onChange) return;
 | 
				
			||||||
 | 
					        openContextModal({
 | 
				
			||||||
 | 
					            title: "Добавление услуги",
 | 
				
			||||||
 | 
					            modal: "addDealService",
 | 
				
			||||||
 | 
					            innerProps: {
 | 
				
			||||||
 | 
					                element: service,
 | 
				
			||||||
 | 
					                onChange,
 | 
				
			||||||
 | 
					                serviceIds
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <BaseTable
 | 
					        <BaseTable
 | 
				
			||||||
            ref={tableRef}
 | 
					            ref={tableRef}
 | 
				
			||||||
@@ -80,7 +95,6 @@ const DealServicesTable: FC<Props> = (
 | 
				
			|||||||
                ),
 | 
					                ),
 | 
				
			||||||
                renderRowActions: ({row}) => (
 | 
					                renderRowActions: ({row}) => (
 | 
				
			||||||
                    <Flex gap="md">
 | 
					                    <Flex gap="md">
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <Tooltip label="Удалить">
 | 
					                        <Tooltip label="Удалить">
 | 
				
			||||||
                            <ActionIcon onClick={() => {
 | 
					                            <ActionIcon onClick={() => {
 | 
				
			||||||
                                if (onDelete) onDelete(row.original);
 | 
					                                if (onDelete) onDelete(row.original);
 | 
				
			||||||
@@ -88,6 +102,13 @@ const DealServicesTable: FC<Props> = (
 | 
				
			|||||||
                                <IconTrash/>
 | 
					                                <IconTrash/>
 | 
				
			||||||
                            </ActionIcon>
 | 
					                            </ActionIcon>
 | 
				
			||||||
                        </Tooltip>
 | 
					                        </Tooltip>
 | 
				
			||||||
 | 
					                        <Tooltip label="Редактировать">
 | 
				
			||||||
 | 
					                            <ActionIcon onClick={() => {
 | 
				
			||||||
 | 
					                                onEditClick(row.original);
 | 
				
			||||||
 | 
					                            }} variant={"default"}>
 | 
				
			||||||
 | 
					                                <IconEdit/>
 | 
				
			||||||
 | 
					                            </ActionIcon>
 | 
				
			||||||
 | 
					                        </Tooltip>
 | 
				
			||||||
                    </Flex>
 | 
					                    </Flex>
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            } as MRT_TableOptions<DealServiceSchema>}
 | 
					            } as MRT_TableOptions<DealServiceSchema>}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
import {MRT_ColumnDef} from "mantine-react-table";
 | 
					import {MRT_ColumnDef} from "mantine-react-table";
 | 
				
			||||||
import {useMemo} from "react";
 | 
					import {useMemo} from "react";
 | 
				
			||||||
import {DealServiceSchema} from "../../../../client";
 | 
					import {DealServiceSchema} from "../../../../client";
 | 
				
			||||||
import PlusMinusInput from "../../../../components/PlusMinusInput/PlusMinusInput.tsx";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
    onChange: (service: DealServiceSchema, quantity: number) => void;
 | 
					    onChange: (service: DealServiceSchema, quantity: number) => void;
 | 
				
			||||||
@@ -11,7 +10,7 @@ type Props = {
 | 
				
			|||||||
export const useDealServicesTableColumns = (props: Props) => {
 | 
					export const useDealServicesTableColumns = (props: Props) => {
 | 
				
			||||||
    const {onChange, data} = props;
 | 
					    const {onChange, data} = props;
 | 
				
			||||||
    const totalPrice = useMemo(() =>
 | 
					    const totalPrice = useMemo(() =>
 | 
				
			||||||
            data.reduce((acc, row) => acc + row.quantity * row.service.price, 0)
 | 
					            data.reduce((acc, row) => acc + row.quantity * row.price, 0)
 | 
				
			||||||
        ,
 | 
					        ,
 | 
				
			||||||
        [data]);
 | 
					        [data]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,34 +27,34 @@ export const useDealServicesTableColumns = (props: Props) => {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
            accessorKey: "service.price",
 | 
					            accessorKey: "price",
 | 
				
			||||||
            header: "Цена",
 | 
					            header: "Цена",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
            accessorKey: "quantity",
 | 
					            accessorKey: "quantity",
 | 
				
			||||||
            header: "Количество",
 | 
					            header: "Количество",
 | 
				
			||||||
            Cell: ({row}) => {
 | 
					            // Cell: ({row}) => {
 | 
				
			||||||
                return (
 | 
					            //     return (
 | 
				
			||||||
                    <PlusMinusInput
 | 
					            //         <PlusMinusInput
 | 
				
			||||||
                        value={row.original.quantity}
 | 
					            //             value={row.original.quantity}
 | 
				
			||||||
                        onChange={(value) => onChange(row.original, value)}
 | 
					            //             onChange={(value) => onChange(row.original, value)}
 | 
				
			||||||
                    />
 | 
					            //         />
 | 
				
			||||||
                )
 | 
					            //     )
 | 
				
			||||||
            }
 | 
					            // }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
            header: "Сумма",
 | 
					            header: "Сумма",
 | 
				
			||||||
            Cell: ({row}) => {
 | 
					            Cell: ({row}) => {
 | 
				
			||||||
                return row.original.quantity * row.original.service.price;
 | 
					                return row.original.quantity * row.original.price;
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            aggregationFn: "sum",
 | 
					            aggregationFn: "sum",
 | 
				
			||||||
            AggregatedCell: ({cell}) => {
 | 
					            AggregatedCell: ({cell}) => {
 | 
				
			||||||
                return <>Итоговая сумма по категории: {" "}
 | 
					                return <>Итоговая сумма по категории: {" "}
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        cell.row.subRows?.reduce((acc, row) =>
 | 
					                        cell.row.subRows?.reduce((acc, row) =>
 | 
				
			||||||
                            acc + row.original.quantity * row.original.service.price, 0)
 | 
					                            acc + row.original.quantity * row.original.price, 0)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                </>;
 | 
					                </>;
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ export const useDealStatusChangeTableColumns = () => {
 | 
				
			|||||||
            accessorKey: "comment",
 | 
					            accessorKey: "comment",
 | 
				
			||||||
            header: "Комментарий",
 | 
					            header: "Комментарий",
 | 
				
			||||||
            Cell: ({row}) =>
 | 
					            Cell: ({row}) =>
 | 
				
			||||||
            <Spoiler onDoubleClick={()=>{console.log("double click")}} maxHeight={80} showLabel={"Показать весь"} hideLabel={"Скрыть"}>
 | 
					            <Spoiler  maxHeight={80} showLabel={"Показать весь"} hideLabel={"Скрыть"}>
 | 
				
			||||||
                <Text style={{wordWrap: "break-word", wordBreak: "break-all", whiteSpace: "normal"}} span>
 | 
					                <Text style={{wordWrap: "break-word", wordBreak: "break-all", whiteSpace: "normal"}} span>
 | 
				
			||||||
                    {row.original.comment}<br/>
 | 
					                    {row.original.comment}<br/>
 | 
				
			||||||
                </Text>
 | 
					                </Text>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					.bottom-panel {
 | 
				
			||||||
 | 
					    padding: rem(10);
 | 
				
			||||||
 | 
					    border-radius: rem(5);
 | 
				
			||||||
 | 
					    @mixin light {
 | 
				
			||||||
 | 
					        background-color: var(--mantine-color-gray-1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    @mixin dark {
 | 
				
			||||||
 | 
					        background-color: var(--mantine-color-dark-5);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -11,6 +11,7 @@ import {IconBarcode, IconBox, IconCalendarUser, IconSettings} from "@tabler/icon
 | 
				
			|||||||
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 styles from './DealEditDrawer.module.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useDealServicesTableState = () => {
 | 
					const useDealServicesTableState = () => {
 | 
				
			||||||
    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
					    const {selectedDeal, setSelectedDeal} = useDealPageContext();
 | 
				
			||||||
@@ -18,11 +19,10 @@ const useDealServicesTableState = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const onServiceUpdate = (service: DealServiceSchema) => {
 | 
					    const onServiceUpdate = (service: DealServiceSchema) => {
 | 
				
			||||||
        if (!selectedDeal) return;
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
        DealService.updateDealServiceQuantity({
 | 
					        DealService.updateDealService({
 | 
				
			||||||
            requestBody: {
 | 
					            requestBody: {
 | 
				
			||||||
                dealId: selectedDeal.id,
 | 
					                dealId: selectedDeal.id,
 | 
				
			||||||
                serviceId: service.service.id,
 | 
					                service
 | 
				
			||||||
                quantity: service.quantity
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).then(async ({ok, message}) => {
 | 
					        }).then(async ({ok, message}) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,14 +72,13 @@ const useDealServicesTableState = () => {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const onServiceCreate = (service: DealServiceSchema) => {
 | 
					    const onServiceCreate = (service: DealServiceSchema) => {
 | 
				
			||||||
        console.log('-------Drawer')
 | 
					 | 
				
			||||||
        console.log(service);
 | 
					 | 
				
			||||||
        if (!selectedDeal) return;
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
        DealService.addDealService({
 | 
					        DealService.addDealService({
 | 
				
			||||||
            requestBody: {
 | 
					            requestBody: {
 | 
				
			||||||
                dealId: selectedDeal.id,
 | 
					                dealId: selectedDeal.id,
 | 
				
			||||||
                serviceId: service.service.id,
 | 
					                serviceId: service.service.id,
 | 
				
			||||||
                quantity: service.quantity
 | 
					                quantity: service.quantity,
 | 
				
			||||||
 | 
					                price: service.price
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).then(async ({ok, message}) => {
 | 
					        }).then(async ({ok, message}) => {
 | 
				
			||||||
            if (!ok) {
 | 
					            if (!ok) {
 | 
				
			||||||
@@ -157,17 +156,14 @@ const useDealProductTableState = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const onProductUpdate = (product: DealProductSchema) => {
 | 
					    const onProductUpdate = (product: DealProductSchema) => {
 | 
				
			||||||
        if (!selectedDeal) return;
 | 
					        if (!selectedDeal) return;
 | 
				
			||||||
        DealService.updateDealProductQuantity({
 | 
					        DealService.updateDealProduct({
 | 
				
			||||||
            requestBody: {
 | 
					            requestBody: {
 | 
				
			||||||
                dealId: selectedDeal.id,
 | 
					                dealId: selectedDeal.id,
 | 
				
			||||||
                productId: product.product.id,
 | 
					                product: product
 | 
				
			||||||
                quantity: product.quantity
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).then(async ({ok, message}) => {
 | 
					        }).then(async ({ok, message}) => {
 | 
				
			||||||
            if (!ok) {
 | 
					 | 
				
			||||||
            notifications.guess(ok, {message});
 | 
					            notifications.guess(ok, {message});
 | 
				
			||||||
                return;
 | 
					            if (!ok) return;
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            await DealService.getDealById({dealId: selectedDeal.id})
 | 
					            await DealService.getDealById({dealId: selectedDeal.id})
 | 
				
			||||||
                .then(setSelectedDeal)
 | 
					                .then(setSelectedDeal)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
@@ -361,7 +357,6 @@ const DealEditDrawer: FC = () => {
 | 
				
			|||||||
                </Tabs.Panel>
 | 
					                </Tabs.Panel>
 | 
				
			||||||
                <Tabs.Panel value={"services"}>
 | 
					                <Tabs.Panel value={"services"}>
 | 
				
			||||||
                    <Box p={rem(10)}>
 | 
					                    <Box p={rem(10)}>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <DealEditDrawerServicesTable/>
 | 
					                        <DealEditDrawerServicesTable/>
 | 
				
			||||||
                    </Box>
 | 
					                    </Box>
 | 
				
			||||||
                </Tabs.Panel>
 | 
					                </Tabs.Panel>
 | 
				
			||||||
@@ -370,9 +365,15 @@ const DealEditDrawer: FC = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                        <DealEditDrawerProductsTable/>
 | 
					                        <DealEditDrawerProductsTable/>
 | 
				
			||||||
                    </Box>
 | 
					                    </Box>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                </Tabs.Panel>
 | 
					                </Tabs.Panel>
 | 
				
			||||||
            </Tabs>
 | 
					            </Tabs>
 | 
				
			||||||
 | 
					            {/*<Flex*/}
 | 
				
			||||||
 | 
					            {/*    h={"10%"}*/}
 | 
				
			||||||
 | 
					            {/*    align={'flex-end'}*/}
 | 
				
			||||||
 | 
					            {/*    justify={"flex-end"}*/}
 | 
				
			||||||
 | 
					            {/*>*/}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {/*</Flex>*/}
 | 
				
			||||||
        </Drawer>
 | 
					        </Drawer>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,6 @@ const AddDealProductModal = ({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const validateServices = (services?: DealProductServiceSchema[]) => {
 | 
					    const validateServices = (services?: DealProductServiceSchema[]) => {
 | 
				
			||||||
        if (!services || services.length == 0) return null;
 | 
					        if (!services || services.length == 0) return null;
 | 
				
			||||||
        console.log("validating...");
 | 
					 | 
				
			||||||
        console.log( services.filter(service => service.service === undefined))
 | 
					 | 
				
			||||||
        return services.find(service => service.service === undefined) ? "Удалите пустые услуги" : null;
 | 
					        return services.find(service => service.service === undefined) ? "Удалите пустые услуги" : null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const form = useForm<Partial<DealProductSchema>>({
 | 
					    const form = useForm<Partial<DealProductSchema>>({
 | 
				
			||||||
@@ -39,11 +37,11 @@ const AddDealProductModal = ({
 | 
				
			|||||||
            services: validateServices
 | 
					            services: validateServices
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    console.log(form.values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onClose = () => {
 | 
					    const onClose = () => {
 | 
				
			||||||
        context.closeContextModal(id);
 | 
					        context.closeContextModal(id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    console.log(form.values)
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <BaseFormModal
 | 
					        <BaseFormModal
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,19 +2,24 @@ import {ContextModalProps} from "@mantine/modals";
 | 
				
			|||||||
import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
 | 
					import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
 | 
				
			||||||
import {DealServiceSchema} from "../../../client";
 | 
					import {DealServiceSchema} from "../../../client";
 | 
				
			||||||
import {useForm} from "@mantine/form";
 | 
					import {useForm} from "@mantine/form";
 | 
				
			||||||
import {NumberInput} from "@mantine/core";
 | 
					import {ComboboxItem, ComboboxItemGroup, NumberInput, OptionsFilter} from "@mantine/core";
 | 
				
			||||||
import ServiceSelect from "../../../components/ServiceSelect/ServiceSelect.tsx";
 | 
					import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
 | 
				
			||||||
 | 
					import {ServiceType} from "../../../shared/enums/ServiceType.ts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = CreateEditFormProps<Partial<DealServiceSchema>>;
 | 
					type RestProps = {
 | 
				
			||||||
 | 
					    serviceIds?: number[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Props = CreateEditFormProps<Partial<DealServiceSchema>> & RestProps;
 | 
				
			||||||
const AddDealServiceModal = ({
 | 
					const AddDealServiceModal = ({
 | 
				
			||||||
                                 context,
 | 
					                                 context,
 | 
				
			||||||
                                 id,
 | 
					                                 id,
 | 
				
			||||||
                                 innerProps
 | 
					                                 innerProps
 | 
				
			||||||
                             }: ContextModalProps<Props>) => {
 | 
					                             }: ContextModalProps<Props>) => {
 | 
				
			||||||
 | 
					    const isEditing = 'element' in innerProps;
 | 
				
			||||||
    const form = useForm<Partial<DealServiceSchema>>({
 | 
					    const form = useForm<Partial<DealServiceSchema>>({
 | 
				
			||||||
        initialValues: {
 | 
					        initialValues: isEditing ? innerProps.element : {
 | 
				
			||||||
            service: undefined,
 | 
					            service: undefined,
 | 
				
			||||||
            quantity: 0,
 | 
					            quantity: 1,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        validate: {
 | 
					        validate: {
 | 
				
			||||||
            service: (service?: DealServiceSchema['service']) => service !== undefined ? null : "Необходимо выбрать услугу",
 | 
					            service: (service?: DealServiceSchema['service']) => service !== undefined ? null : "Необходимо выбрать услугу",
 | 
				
			||||||
@@ -25,6 +30,16 @@ const AddDealServiceModal = ({
 | 
				
			|||||||
        context.closeContextModal(id);
 | 
					        context.closeContextModal(id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const serviceOptionsFilter = ({options}: { options: ComboboxItemGroup[] }) => {
 | 
				
			||||||
 | 
					        if (!innerProps.serviceIds) return options;
 | 
				
			||||||
 | 
					        const productServiceIds = innerProps.serviceIds;
 | 
				
			||||||
 | 
					        return (options as ComboboxItemGroup[]).map(({items, group}) => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                group,
 | 
				
			||||||
 | 
					                items: items.filter(item => !productServiceIds.includes(parseInt((item as ComboboxItem).value)))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <BaseFormModal
 | 
					        <BaseFormModal
 | 
				
			||||||
@@ -34,10 +49,27 @@ const AddDealServiceModal = ({
 | 
				
			|||||||
            onClose={onClose}>
 | 
					            onClose={onClose}>
 | 
				
			||||||
            <BaseFormModal.Body>
 | 
					            <BaseFormModal.Body>
 | 
				
			||||||
                <>
 | 
					                <>
 | 
				
			||||||
                    <ServiceSelect
 | 
					                    <ServiceWithPriceInput
 | 
				
			||||||
                        placeholder={"Выберите услугу"}
 | 
					                        serviceProps={{
 | 
				
			||||||
                        label={"Услуга"}
 | 
					                            ...form.getInputProps('service'),
 | 
				
			||||||
                        {...form.getInputProps('service')}
 | 
					                            label: "Услуга",
 | 
				
			||||||
 | 
					                            placeholder: "Выберите услугу",
 | 
				
			||||||
 | 
					                            style: {width: '100%'},
 | 
				
			||||||
 | 
					                            disabled: isEditing,
 | 
				
			||||||
 | 
					                            filter: serviceOptionsFilter as OptionsFilter
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        priceProps={{
 | 
				
			||||||
 | 
					                            ...form.getInputProps('price'),
 | 
				
			||||||
 | 
					                            label: "Цена",
 | 
				
			||||||
 | 
					                            placeholder: "Введите цену",
 | 
				
			||||||
 | 
					                            style: {width: '100%'}
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        quantity={form.values.quantity || 1}
 | 
				
			||||||
 | 
					                        containerProps={{
 | 
				
			||||||
 | 
					                            direction: "column",
 | 
				
			||||||
 | 
					                            style: {width: "100%"}
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        filterType={ServiceType.DEAL_SERVICE}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                    <NumberInput
 | 
					                    <NumberInput
 | 
				
			||||||
                        placeholder={"Введите количество"}
 | 
					                        placeholder={"Введите количество"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import {SegmentedControl, SegmentedControlProps} from "@mantine/core";
 | 
				
			||||||
 | 
					import {ServiceType} from "../../../../shared/enums/ServiceType.ts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = Omit<SegmentedControlProps, 'data'>;
 | 
				
			||||||
 | 
					const data = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        label: 'Для товара',
 | 
				
			||||||
 | 
					        value: ServiceType.PRODUCT_SERVICE.toString()
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        label: 'Для сделки',
 | 
				
			||||||
 | 
					        value: ServiceType.DEAL_SERVICE.toString()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					const ServiceTypeSegmentedControl: FC<Props> = (props) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <SegmentedControl
 | 
				
			||||||
 | 
					            data={data}
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default ServiceTypeSegmentedControl
 | 
				
			||||||
@@ -44,7 +44,6 @@ const CreateServiceModal = ({
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log(form.values)
 | 
					 | 
				
			||||||
    const onCancelClick = () => {
 | 
					    const onCancelClick = () => {
 | 
				
			||||||
        context.closeContextModal(id);
 | 
					        context.closeContextModal(id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,4 +9,9 @@
 | 
				
			|||||||
    padding: rem(5);
 | 
					    padding: rem(5);
 | 
				
			||||||
    gap: rem(10);
 | 
					    gap: rem(10);
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.top-panel-last-item {
 | 
				
			||||||
 | 
					    margin-left: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import {FC} from "react";
 | 
					import {FC, useState} from "react";
 | 
				
			||||||
import ServicesTable from "../components/ServicesTable/ServicesTable.tsx";
 | 
					import ServicesTable from "../components/ServicesTable/ServicesTable.tsx";
 | 
				
			||||||
import useServicesList from "../hooks/useServicesList.tsx";
 | 
					import useServicesList from "../hooks/useServicesList.tsx";
 | 
				
			||||||
import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
 | 
					import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
 | 
				
			||||||
@@ -7,10 +7,12 @@ import {Button, Text} from "@mantine/core";
 | 
				
			|||||||
import {ServiceCategorySchema, ServiceSchema, ServiceService} from "../../../client";
 | 
					import {ServiceCategorySchema, ServiceSchema, ServiceService} from "../../../client";
 | 
				
			||||||
import {notifications} from "../../../shared/lib/notifications.ts";
 | 
					import {notifications} from "../../../shared/lib/notifications.ts";
 | 
				
			||||||
import {modals} from "@mantine/modals";
 | 
					import {modals} from "@mantine/modals";
 | 
				
			||||||
 | 
					import ServiceTypeSegmentedControl from "../components/ServiceTypeSegmentedControl/ServiceTypeSegmentedControl.tsx";
 | 
				
			||||||
 | 
					import {ServiceType} from "../../../shared/enums/ServiceType.ts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ServicesPage: FC = () => {
 | 
					export const ServicesPage: FC = () => {
 | 
				
			||||||
    const {services, refetch} = useServicesList();
 | 
					    const {services, refetch} = useServicesList();
 | 
				
			||||||
 | 
					    const [serviceType, setServiceType] = useState(ServiceType.DEAL_SERVICE)
 | 
				
			||||||
    // region Service create
 | 
					    // region Service create
 | 
				
			||||||
    const onCreateClick = () => {
 | 
					    const onCreateClick = () => {
 | 
				
			||||||
        modals.openContextModal({
 | 
					        modals.openContextModal({
 | 
				
			||||||
@@ -90,13 +92,18 @@ export const ServicesPage: FC = () => {
 | 
				
			|||||||
                <div className={styles['top-panel']}>
 | 
					                <div className={styles['top-panel']}>
 | 
				
			||||||
                    <Button onClick={onCreateClick} variant={"default"}>Создать услугу</Button>
 | 
					                    <Button onClick={onCreateClick} variant={"default"}>Создать услугу</Button>
 | 
				
			||||||
                    <Button onClick={onCreateCategoryClick} variant={"default"}>Создать категорию</Button>
 | 
					                    <Button onClick={onCreateCategoryClick} variant={"default"}>Создать категорию</Button>
 | 
				
			||||||
 | 
					                    <ServiceTypeSegmentedControl
 | 
				
			||||||
 | 
					                        className={styles['top-panel-last-item']}
 | 
				
			||||||
 | 
					                        value={serviceType.toString()}
 | 
				
			||||||
 | 
					                        onChange={(event) => setServiceType(parseInt(event))}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </PageBlock>
 | 
					            </PageBlock>
 | 
				
			||||||
            <PageBlock>
 | 
					            <PageBlock>
 | 
				
			||||||
                <ServicesTable
 | 
					                <ServicesTable
 | 
				
			||||||
                    onDelete={onServiceDelete}
 | 
					                    onDelete={onServiceDelete}
 | 
				
			||||||
                    onChange={onServiceUpdate}
 | 
					                    onChange={onServiceUpdate}
 | 
				
			||||||
                    items={services}
 | 
					                    items={services.filter(service => service.serviceType == serviceType)}
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
            </PageBlock>
 | 
					            </PageBlock>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,73 +1,14 @@
 | 
				
			|||||||
import {createLazyFileRoute} from "@tanstack/react-router";
 | 
					import {createLazyFileRoute} from "@tanstack/react-router";
 | 
				
			||||||
import ServiceSelectNew from "../components/Selects/ServiceSelectNew/ServiceSelectNew.tsx";
 | 
					 | 
				
			||||||
import {ServiceType} from "../shared/enums/ServiceType.ts";
 | 
					 | 
				
			||||||
import ServiceWithPriceInput from "../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
 | 
					 | 
				
			||||||
import {useEffect, useState} from "react";
 | 
					 | 
				
			||||||
import {ServiceSchema, ServiceService} from "../client";
 | 
					 | 
				
			||||||
import {NumberInput} from "@mantine/core";
 | 
					 | 
				
			||||||
import {isNumber} from "lodash";
 | 
					 | 
				
			||||||
import useServicesList from "../pages/ServicesPage/hooks/useServicesList.tsx";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Route = createLazyFileRoute('/test')({
 | 
					export const Route = createLazyFileRoute('/test')({
 | 
				
			||||||
    component: TestPage
 | 
					    component: TestPage
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const data = [{
 | 
					 | 
				
			||||||
    label: "test",
 | 
					 | 
				
			||||||
    value: '0'
 | 
					 | 
				
			||||||
},
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        label: "test2",
 | 
					 | 
				
			||||||
        value: '1'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TestPage() {
 | 
					function TestPage() {
 | 
				
			||||||
    const [service, setService] = useState<ServiceSchema | undefined>({
 | 
					 | 
				
			||||||
        "id": 96,
 | 
					 | 
				
			||||||
        "name": "123",
 | 
					 | 
				
			||||||
        "category": {"id": 1, "name": "Услуги по работе с товаром с учетом суммы всех сторон в см."},
 | 
					 | 
				
			||||||
        "price": 0,
 | 
					 | 
				
			||||||
        "serviceType": 1,
 | 
					 | 
				
			||||||
        "priceRanges": [{"id": 4, "fromQuantity": 1, "toQuantity": 200, "price": 35}, {
 | 
					 | 
				
			||||||
            "id": 3,
 | 
					 | 
				
			||||||
            "fromQuantity": 201,
 | 
					 | 
				
			||||||
            "toQuantity": 300,
 | 
					 | 
				
			||||||
            "price": 24
 | 
					 | 
				
			||||||
        }]
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    const [price, setPrice] = useState<number | string>();
 | 
					 | 
				
			||||||
    const [q, setQ] = useState(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log('service:---------');
 | 
					 | 
				
			||||||
    console.log(service);
 | 
					 | 
				
			||||||
    console.log('price:---------');
 | 
					 | 
				
			||||||
    console.log(price);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
            <NumberInput
 | 
					
 | 
				
			||||||
                value={q}
 | 
					 | 
				
			||||||
                onChange={event => {
 | 
					 | 
				
			||||||
                    if (!isNumber(event)) return;
 | 
					 | 
				
			||||||
                    setQ(event);
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
            <ServiceWithPriceInput
 | 
					 | 
				
			||||||
                priceProps={{
 | 
					 | 
				
			||||||
                    onChange: setPrice,
 | 
					 | 
				
			||||||
                    value: price,
 | 
					 | 
				
			||||||
                    label: "Цена"
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
                quantity={q}
 | 
					 | 
				
			||||||
                serviceProps={{
 | 
					 | 
				
			||||||
                    onChange: setService,
 | 
					 | 
				
			||||||
                    value: service,
 | 
					 | 
				
			||||||
                    label: "Услуга"
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user