feat: shipping warehouse and cost
This commit is contained in:
		@@ -80,6 +80,7 @@ export type { DealUpdateServiceResponse } from './models/DealUpdateServiceRespon
 | 
				
			|||||||
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';
 | 
				
			||||||
 | 
					export type { GetAllShippingWarehousesResponse } from './models/GetAllShippingWarehousesResponse';
 | 
				
			||||||
export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest';
 | 
					export type { GetBarcodeTemplateByIdRequest } from './models/GetBarcodeTemplateByIdRequest';
 | 
				
			||||||
export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse';
 | 
					export type { GetBarcodeTemplateByIdResponse } from './models/GetBarcodeTemplateByIdResponse';
 | 
				
			||||||
export type { GetProductBarcodePdfRequest } from './models/GetProductBarcodePdfRequest';
 | 
					export type { GetProductBarcodePdfRequest } from './models/GetProductBarcodePdfRequest';
 | 
				
			||||||
@@ -116,6 +117,7 @@ export type { ServicePriceRangeSchema } from './models/ServicePriceRangeSchema';
 | 
				
			|||||||
export type { ServiceSchema } from './models/ServiceSchema';
 | 
					export type { ServiceSchema } from './models/ServiceSchema';
 | 
				
			||||||
export type { ServiceUpdateRequest } from './models/ServiceUpdateRequest';
 | 
					export type { ServiceUpdateRequest } from './models/ServiceUpdateRequest';
 | 
				
			||||||
export type { ServiceUpdateResponse } from './models/ServiceUpdateResponse';
 | 
					export type { ServiceUpdateResponse } from './models/ServiceUpdateResponse';
 | 
				
			||||||
 | 
					export type { ShippingWarehouseSchema } from './models/ShippingWarehouseSchema';
 | 
				
			||||||
export type { UserSchema } from './models/UserSchema';
 | 
					export type { UserSchema } from './models/UserSchema';
 | 
				
			||||||
export type { ValidationError } from './models/ValidationError';
 | 
					export type { ValidationError } from './models/ValidationError';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,3 +127,4 @@ export { ClientService } from './services/ClientService';
 | 
				
			|||||||
export { DealService } from './services/DealService';
 | 
					export { DealService } from './services/DealService';
 | 
				
			||||||
export { ProductService } from './services/ProductService';
 | 
					export { ProductService } from './services/ProductService';
 | 
				
			||||||
export { ServiceService } from './services/ServiceService';
 | 
					export { ServiceService } from './services/ServiceService';
 | 
				
			||||||
 | 
					export { ShippingWarehouseService } from './services/ShippingWarehouseService';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,5 +7,6 @@ export type DealQuickCreateRequest = {
 | 
				
			|||||||
    clientName: string;
 | 
					    clientName: string;
 | 
				
			||||||
    comment: string;
 | 
					    comment: string;
 | 
				
			||||||
    acceptanceDate: string;
 | 
					    acceptanceDate: string;
 | 
				
			||||||
 | 
					    shippingWarehouse: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ import type { ClientSchema } from './ClientSchema';
 | 
				
			|||||||
import type { DealProductSchema } from './DealProductSchema';
 | 
					import type { DealProductSchema } from './DealProductSchema';
 | 
				
			||||||
import type { DealServiceSchema } from './DealServiceSchema';
 | 
					import type { DealServiceSchema } from './DealServiceSchema';
 | 
				
			||||||
import type { DealStatusHistorySchema } from './DealStatusHistorySchema';
 | 
					import type { DealStatusHistorySchema } from './DealStatusHistorySchema';
 | 
				
			||||||
 | 
					import type { ShippingWarehouseSchema } from './ShippingWarehouseSchema';
 | 
				
			||||||
export type DealSchema = {
 | 
					export type DealSchema = {
 | 
				
			||||||
    id: number;
 | 
					    id: number;
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
@@ -19,5 +20,6 @@ export type DealSchema = {
 | 
				
			|||||||
    isCompleted: boolean;
 | 
					    isCompleted: boolean;
 | 
				
			||||||
    client: ClientSchema;
 | 
					    client: ClientSchema;
 | 
				
			||||||
    comment: string;
 | 
					    comment: string;
 | 
				
			||||||
 | 
					    shippingWarehouse?: (ShippingWarehouseSchema | null);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								src/client/models/GetAllShippingWarehousesResponse.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/GetAllShippingWarehousesResponse.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { ShippingWarehouseSchema } from './ShippingWarehouseSchema';
 | 
				
			||||||
 | 
					export type GetAllShippingWarehousesResponse = {
 | 
				
			||||||
 | 
					    shippingWarehouses: Array<ShippingWarehouseSchema>;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,5 +11,6 @@ export type ServiceSchema = {
 | 
				
			|||||||
    price: number;
 | 
					    price: number;
 | 
				
			||||||
    serviceType: number;
 | 
					    serviceType: number;
 | 
				
			||||||
    priceRanges: Array<ServicePriceRangeSchema>;
 | 
					    priceRanges: Array<ServicePriceRangeSchema>;
 | 
				
			||||||
 | 
					    cost: (number | null);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								src/client/models/ShippingWarehouseSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/models/ShippingWarehouseSchema.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					export type ShippingWarehouseSchema = {
 | 
				
			||||||
 | 
					    id: number;
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								src/client/services/ShippingWarehouseService.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/client/services/ShippingWarehouseService.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					/* generated using openapi-typescript-codegen -- do no edit */
 | 
				
			||||||
 | 
					/* istanbul ignore file */
 | 
				
			||||||
 | 
					/* tslint:disable */
 | 
				
			||||||
 | 
					/* eslint-disable */
 | 
				
			||||||
 | 
					import type { GetAllShippingWarehousesResponse } from '../models/GetAllShippingWarehousesResponse';
 | 
				
			||||||
 | 
					import type { CancelablePromise } from '../core/CancelablePromise';
 | 
				
			||||||
 | 
					import { OpenAPI } from '../core/OpenAPI';
 | 
				
			||||||
 | 
					import { request as __request } from '../core/request';
 | 
				
			||||||
 | 
					export class ShippingWarehouseService {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get All
 | 
				
			||||||
 | 
					     * @returns GetAllShippingWarehousesResponse Successful Response
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static getAllShippingWarehouses(): CancelablePromise<GetAllShippingWarehousesResponse> {
 | 
				
			||||||
 | 
					        return __request(OpenAPI, {
 | 
				
			||||||
 | 
					            method: 'GET',
 | 
				
			||||||
 | 
					            url: '/shipping-warehouse/get-all',
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,19 +5,22 @@ import {useForm} from "@mantine/form";
 | 
				
			|||||||
import styles from './CreateDealForm.module.css';
 | 
					import styles from './CreateDealForm.module.css';
 | 
				
			||||||
import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx";
 | 
					import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx";
 | 
				
			||||||
import {DateTimePicker} from "@mantine/dates";
 | 
					import {DateTimePicker} from "@mantine/dates";
 | 
				
			||||||
 | 
					import ShippingWarehouseAutocomplete
 | 
				
			||||||
 | 
					    from "../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
    onSubmit: (quickDeal: QuickDeal) => void
 | 
					    onSubmit: (quickDeal: QuickDeal) => void
 | 
				
			||||||
    onCancel: () => void;
 | 
					    onCancel: () => void;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
					const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
				
			||||||
    const form = useForm({
 | 
					    const form = useForm<QuickDeal>({
 | 
				
			||||||
        initialValues: {
 | 
					        initialValues: {
 | 
				
			||||||
            name: '',
 | 
					            name: '',
 | 
				
			||||||
            clientName: '',
 | 
					            clientName: '',
 | 
				
			||||||
            clientAddress: '',
 | 
					            clientAddress: '',
 | 
				
			||||||
            comment: '',
 | 
					            comment: '',
 | 
				
			||||||
            acceptanceDate: new Date()
 | 
					            acceptanceDate: new Date(),
 | 
				
			||||||
 | 
					            shippingWarehouse: ''
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
@@ -25,7 +28,6 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
				
			|||||||
            style={{width: '100%'}}
 | 
					            style={{width: '100%'}}
 | 
				
			||||||
            onSubmit={form.onSubmit((values) => onSubmit(values))}
 | 
					            onSubmit={form.onSubmit((values) => onSubmit(values))}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
 | 
					 | 
				
			||||||
            <div style={{
 | 
					            <div style={{
 | 
				
			||||||
                display: 'flex',
 | 
					                display: 'flex',
 | 
				
			||||||
                flexDirection: 'column',
 | 
					                flexDirection: 'column',
 | 
				
			||||||
@@ -43,6 +45,10 @@ const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
 | 
				
			|||||||
                    <ClientAutocomplete
 | 
					                    <ClientAutocomplete
 | 
				
			||||||
                        nameRestProps={form.getInputProps('clientName')}
 | 
					                        nameRestProps={form.getInputProps('clientName')}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
 | 
					                    <ShippingWarehouseAutocomplete
 | 
				
			||||||
 | 
					                        {...form.getInputProps('shippingWarehouse')}
 | 
				
			||||||
 | 
					                        placeholder={'Склад отгрузки'}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div className={styles['inputs']}>
 | 
					                <div className={styles['inputs']}>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										65
									
								
								src/components/ObjectAutocomplete/ObjectAutocomplete.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/components/ObjectAutocomplete/ObjectAutocomplete.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					import {Autocomplete, AutocompleteProps} from "@mantine/core";
 | 
				
			||||||
 | 
					import {useEffect, useMemo, useState} from "react";
 | 
				
			||||||
 | 
					import {ObjectWithNameAndId} from "../../types/utils.ts";
 | 
				
			||||||
 | 
					import {omit} from "lodash";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AutocompleteObjectType<T extends ObjectWithNameAndId> = T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ControlledValueProps<T extends ObjectWithNameAndId> = {
 | 
				
			||||||
 | 
					    value: AutocompleteObjectType<T>,
 | 
				
			||||||
 | 
					    onChange: (value: string) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RestProps<T extends ObjectWithNameAndId> = {
 | 
				
			||||||
 | 
					    defaultValue?: AutocompleteObjectType<T>
 | 
				
			||||||
 | 
					    onChange: (value: string) => void;
 | 
				
			||||||
 | 
					    data: AutocompleteObjectType<T>[];
 | 
				
			||||||
 | 
					    filterBy?: (item: AutocompleteObjectType<T>) => boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type ObjectAutocompleteProps<T extends ObjectWithNameAndId> =
 | 
				
			||||||
 | 
					    (RestProps<T> & Partial<ControlledValueProps<T>>)
 | 
				
			||||||
 | 
					    & Omit<AutocompleteProps, 'value' | 'onChange' | 'data'>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ObjectAutocomplete = <T extends ObjectWithNameAndId, >(props: ObjectAutocompleteProps<T>) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const isControlled = 'value' in props;
 | 
				
			||||||
 | 
					    const [internalValue, setInternalValue] = useState<undefined | string>(props.defaultValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const value = isControlled ? props.value?.name : internalValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const data = useMemo(() => {
 | 
				
			||||||
 | 
					        const propsData = props.filterBy ? props.data.filter(props.filterBy) : props.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return propsData.map(item => ({
 | 
				
			||||||
 | 
					            label: item.name,
 | 
				
			||||||
 | 
					            value: item.id.toString()
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					    }, [props.data]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleOnChange = (event: string | null) => {
 | 
				
			||||||
 | 
					        if (!event) return;
 | 
				
			||||||
 | 
					        if (isControlled) {
 | 
				
			||||||
 | 
					            props.onChange(event);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        setInternalValue(event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (isControlled || !internalValue) return;
 | 
				
			||||||
 | 
					        props.onChange(internalValue);
 | 
				
			||||||
 | 
					    }, [internalValue]);
 | 
				
			||||||
 | 
					    const restProps = omit(props, ['filterBy', 'groupBy']);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Autocomplete
 | 
				
			||||||
 | 
					            {...restProps}
 | 
				
			||||||
 | 
					            value={value?.toString()}
 | 
				
			||||||
 | 
					            onChange={handleOnChange}
 | 
				
			||||||
 | 
					            data={data}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ObjectAutocomplete;
 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					import ObjectAutocomplete, {ObjectAutocompleteProps} from "../../ObjectAutocomplete/ObjectAutocomplete.tsx";
 | 
				
			||||||
 | 
					import useShippingWarehousesList from "./hooks/useShippingWarehousesList.tsx";
 | 
				
			||||||
 | 
					import {FC} from "react";
 | 
				
			||||||
 | 
					import {ShippingWarehouseSchema} from "../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = Omit<ObjectAutocompleteProps<ShippingWarehouseSchema>, 'data'>;
 | 
				
			||||||
 | 
					const ShippingWarehouseAutocomplete: FC<Props> = (props) => {
 | 
				
			||||||
 | 
					    const {shippingWarehouses} = useShippingWarehousesList();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ObjectAutocomplete
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					            data={shippingWarehouses}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default ShippingWarehouseAutocomplete;
 | 
				
			||||||
@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import {useQuery} from "@tanstack/react-query";
 | 
				
			||||||
 | 
					import {ShippingWarehouseService} from "../../../../client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useShippingWarehousesList = () => {
 | 
				
			||||||
 | 
					    const {isPending, error, data, refetch} = useQuery({
 | 
				
			||||||
 | 
					        queryKey: ['getAllShippingWarehouses'],
 | 
				
			||||||
 | 
					        queryFn: ShippingWarehouseService.getAllShippingWarehouses
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    const shippingWarehouses = isPending || error || !data ? [] : data.shippingWarehouses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {shippingWarehouses, refetch}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export default useShippingWarehousesList;
 | 
				
			||||||
@@ -41,7 +41,6 @@ const queryClient = new QueryClient();
 | 
				
			|||||||
OpenAPI.BASE = import.meta.env.VITE_API_URL
 | 
					OpenAPI.BASE = import.meta.env.VITE_API_URL
 | 
				
			||||||
OpenAPI.TOKEN = JSON.parse(localStorage.getItem('authState') || "{}")['accessToken'];
 | 
					OpenAPI.TOKEN = JSON.parse(localStorage.getItem('authState') || "{}")['accessToken'];
 | 
				
			||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
 | 
					ReactDOM.createRoot(document.getElementById('root')!).render(
 | 
				
			||||||
    // <React.StrictMode>
 | 
					 | 
				
			||||||
    <Provider store={store}>
 | 
					    <Provider store={store}>
 | 
				
			||||||
        <QueryClientProvider client={queryClient}>
 | 
					        <QueryClientProvider client={queryClient}>
 | 
				
			||||||
            <MantineProvider defaultColorScheme={"dark"}>
 | 
					            <MantineProvider defaultColorScheme={"dark"}>
 | 
				
			||||||
@@ -54,5 +53,4 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
 | 
				
			|||||||
            </MantineProvider>
 | 
					            </MantineProvider>
 | 
				
			||||||
        </QueryClientProvider>
 | 
					        </QueryClientProvider>
 | 
				
			||||||
    </Provider>
 | 
					    </Provider>
 | 
				
			||||||
    // </React.StrictMode>,
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,18 +30,15 @@ export const useDealServicesTableColumns = (props: Props) => {
 | 
				
			|||||||
            accessorKey: "price",
 | 
					            accessorKey: "price",
 | 
				
			||||||
            header: "Цена",
 | 
					            header: "Цена",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            accessorKey: "service.cost",
 | 
				
			||||||
 | 
					            header: "Себестоимость"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
            accessorKey: "quantity",
 | 
					            accessorKey: "quantity",
 | 
				
			||||||
            header: "Количество",
 | 
					            header: "Количество",
 | 
				
			||||||
            // Cell: ({row}) => {
 | 
					 | 
				
			||||||
            //     return (
 | 
					 | 
				
			||||||
            //         <PlusMinusInput
 | 
					 | 
				
			||||||
            //             value={row.original.quantity}
 | 
					 | 
				
			||||||
            //             onChange={(value) => onChange(row.original, value)}
 | 
					 | 
				
			||||||
            //         />
 | 
					 | 
				
			||||||
            //     )
 | 
					 | 
				
			||||||
            // }
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -287,7 +287,6 @@ const DealEditDrawerProductsTable = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const useDealStatusChangeState = () => {
 | 
					const useDealStatusChangeState = () => {
 | 
				
			||||||
    const {selectedDeal} = useDealPageContext();
 | 
					    const {selectedDeal} = useDealPageContext();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        statusHistory: selectedDeal?.statusHistory || []
 | 
					        statusHistory: selectedDeal?.statusHistory || []
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -342,12 +341,6 @@ const DealEditDrawer: FC = () => {
 | 
				
			|||||||
                    <Tabs.Tab value={"servicesAndProducts"} leftSection={<IconBox/>}>
 | 
					                    <Tabs.Tab value={"servicesAndProducts"} leftSection={<IconBox/>}>
 | 
				
			||||||
                        Товары и услуги
 | 
					                        Товары и услуги
 | 
				
			||||||
                    </Tabs.Tab>
 | 
					                    </Tabs.Tab>
 | 
				
			||||||
                    {/*<Tabs.Tab value={"services"} leftSection={<IconBox/>}>*/}
 | 
					 | 
				
			||||||
                    {/*    Услуги*/}
 | 
					 | 
				
			||||||
                    {/*</Tabs.Tab>*/}
 | 
					 | 
				
			||||||
                    {/*<Tabs.Tab value={"products"} leftSection={<IconBarcode/>}>*/}
 | 
					 | 
				
			||||||
                    {/*    Товары*/}
 | 
					 | 
				
			||||||
                    {/*</Tabs.Tab>*/}
 | 
					 | 
				
			||||||
                </Tabs.List>
 | 
					                </Tabs.List>
 | 
				
			||||||
                <Tabs.Panel value={"general"}>
 | 
					                <Tabs.Panel value={"general"}>
 | 
				
			||||||
                    <Box h={"100%"} w={"100%"} p={rem(10)}>
 | 
					                    <Box h={"100%"} w={"100%"} p={rem(10)}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,7 +64,6 @@ const Content: FC<Props> = ({deal}) => {
 | 
				
			|||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
 | 
					        <form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
 | 
				
			||||||
            <Flex direction={'column'}>
 | 
					            <Flex direction={'column'}>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                <Fieldset legend={"Общие параметры"}>
 | 
					                <Fieldset legend={"Общие параметры"}>
 | 
				
			||||||
                    <Flex direction={"column"} gap={rem(10)}>
 | 
					                    <Flex direction={"column"} gap={rem(10)}>
 | 
				
			||||||
                        <TextInput
 | 
					                        <TextInput
 | 
				
			||||||
@@ -83,12 +82,17 @@ const Content: FC<Props> = ({deal}) => {
 | 
				
			|||||||
                            placeholder={"Текущий статус"}
 | 
					                            placeholder={"Текущий статус"}
 | 
				
			||||||
                            label={"Текущий статус"}
 | 
					                            label={"Текущий статус"}
 | 
				
			||||||
                            value={DealStatusDictionary[deal.currentStatus as DealStatus]}/>
 | 
					                            value={DealStatusDictionary[deal.currentStatus as DealStatus]}/>
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <Textarea
 | 
					                        <Textarea
 | 
				
			||||||
                            label={'Коментарий к сделке'}
 | 
					                            label={'Коментарий к сделке'}
 | 
				
			||||||
                            placeholder={'Введите коментарий к сделке'}
 | 
					                            placeholder={'Введите коментарий к сделке'}
 | 
				
			||||||
                            {...form.getInputProps('comment')}
 | 
					                            {...form.getInputProps('comment')}
 | 
				
			||||||
                        />
 | 
					                        />
 | 
				
			||||||
 | 
					                        <TextInput
 | 
				
			||||||
 | 
					                            disabled
 | 
				
			||||||
 | 
					                            placeholder={"Введите склад отгрузки"}
 | 
				
			||||||
 | 
					                            label={"Склад отгрузки"}
 | 
				
			||||||
 | 
					                            value={form.values.shippingWarehouse?.name}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
                    </Flex>
 | 
					                    </Flex>
 | 
				
			||||||
                </Fieldset>
 | 
					                </Fieldset>
 | 
				
			||||||
                <Fieldset legend={"Клиент"}>
 | 
					                <Fieldset legend={"Клиент"}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,7 +58,7 @@ const ProductAndServiceTab: FC = () => {
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </Flex>
 | 
					                </Flex>
 | 
				
			||||||
                <Flex direction={"column"} className={styles['deal-container-wrapper']}>
 | 
					                <Flex direction={"column"} className={styles['deal-container-wrapper']}>
 | 
				
			||||||
                    <Title order={3}>Общая стоимость всех услуг: {getTotalPrice()}</Title>
 | 
					                    <Title order={3}>Общая стоимость всех услуг: {getTotalPrice().toLocaleString("ru")}₽</Title>
 | 
				
			||||||
                </Flex>
 | 
					                </Flex>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,15 +9,21 @@ type Props = {
 | 
				
			|||||||
const useProductServicesTableColumns = (props: Props) => {
 | 
					const useProductServicesTableColumns = (props: Props) => {
 | 
				
			||||||
    const {data, quantity} = props;
 | 
					    const {data, quantity} = props;
 | 
				
			||||||
    const totalPrice = useMemo(() => data.reduce((acc, row) => acc + (row.price * quantity), 0), [data, quantity]);
 | 
					    const totalPrice = useMemo(() => data.reduce((acc, row) => acc + (row.price * quantity), 0), [data, quantity]);
 | 
				
			||||||
 | 
					    const totalCost = useMemo(() => data.reduce((acc, row) => acc + ((row.service.cost || 0) * quantity), 0), [data, quantity]);
 | 
				
			||||||
    return useMemo<MRT_ColumnDef<DealProductServiceSchema>[]>(() => [
 | 
					    return useMemo<MRT_ColumnDef<DealProductServiceSchema>[]>(() => [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            accessorKey: "service.name",
 | 
					            accessorKey: "service.name",
 | 
				
			||||||
            header: "Услуга",
 | 
					            header: "Услуга",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            accessorKey: "service.cost",
 | 
				
			||||||
 | 
					            header: "Себестоимость",
 | 
				
			||||||
 | 
					            Footer: () => <>Итоговая себестоимость: {totalCost.toLocaleString("ru")}₽</>,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            accessorKey: "price",
 | 
					            accessorKey: "price",
 | 
				
			||||||
            header: "Цена",
 | 
					            header: "Цена",
 | 
				
			||||||
            Footer: () => <>Итог: {totalPrice}₽</>,
 | 
					            Footer: () => <>Итог: {totalPrice.toLocaleString("ru")}₽</>,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ], [totalPrice]);
 | 
					    ], [totalPrice]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,8 +41,14 @@ export const useServicesTableColumns = () => {
 | 
				
			|||||||
            enableGrouping: false,
 | 
					            enableGrouping: false,
 | 
				
			||||||
            enableSorting: false,
 | 
					            enableSorting: false,
 | 
				
			||||||
            Cell: ({row}) => getPriceRow(row.original)
 | 
					            Cell: ({row}) => getPriceRow(row.original)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            accessorKey: "cost",
 | 
				
			||||||
 | 
					            header: "Себестоимость",
 | 
				
			||||||
 | 
					            enableGrouping: false,
 | 
				
			||||||
 | 
					            enableSorting: false,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ], []);
 | 
					    ], []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2,7 +2,7 @@ import {ServicePriceRangeSchema, ServiceSchema} from "../../../client";
 | 
				
			|||||||
import {useForm} from "@mantine/form";
 | 
					import {useForm} from "@mantine/form";
 | 
				
			||||||
import {ContextModalProps} from "@mantine/modals";
 | 
					import {ContextModalProps} from "@mantine/modals";
 | 
				
			||||||
import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
 | 
					import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
 | 
				
			||||||
import {TextInput} from "@mantine/core";
 | 
					import {NumberInput, TextInput} from "@mantine/core";
 | 
				
			||||||
import ServiceCategorySelect from "../components/ServiceCategorySelect/ServiceCategorySelect.tsx";
 | 
					import ServiceCategorySelect from "../components/ServiceCategorySelect/ServiceCategorySelect.tsx";
 | 
				
			||||||
import ServiceTypeSelect from "../components/ServiceTypeSelect/ServiceTypeSelect.tsx";
 | 
					import ServiceTypeSelect from "../components/ServiceTypeSelect/ServiceTypeSelect.tsx";
 | 
				
			||||||
import ServicePriceInput from "../components/ServicePriceInput/ServicePriceInput.tsx";
 | 
					import ServicePriceInput from "../components/ServicePriceInput/ServicePriceInput.tsx";
 | 
				
			||||||
@@ -25,7 +25,8 @@ const CreateServiceModal = ({
 | 
				
			|||||||
            name: ''
 | 
					            name: ''
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        serviceType: -1,
 | 
					        serviceType: -1,
 | 
				
			||||||
        priceRanges: [] as ServicePriceRangeSchema[]
 | 
					        priceRanges: [] as ServicePriceRangeSchema[],
 | 
				
			||||||
 | 
					        cost: null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const form = useForm<ServiceSchema>({
 | 
					    const form = useForm<ServiceSchema>({
 | 
				
			||||||
@@ -72,6 +73,12 @@ const CreateServiceModal = ({
 | 
				
			|||||||
                        label={"Тип услуги"}
 | 
					                        label={"Тип услуги"}
 | 
				
			||||||
                        {...form.getInputProps('serviceType')}
 | 
					                        {...form.getInputProps('serviceType')}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
 | 
					                    <NumberInput
 | 
				
			||||||
 | 
					                        placeholder={"Введите себестоимость услуги"}
 | 
				
			||||||
 | 
					                        label={"Себестоимость услуги"}
 | 
				
			||||||
 | 
					                        hideControls
 | 
				
			||||||
 | 
					                        {...form.getInputProps('cost')}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
                    <ServicePriceInput
 | 
					                    <ServicePriceInput
 | 
				
			||||||
                        singlePriceInputProps={{
 | 
					                        singlePriceInputProps={{
 | 
				
			||||||
                            hideControls: true,
 | 
					                            hideControls: true,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ export const Route = createLazyFileRoute('/test')({
 | 
				
			|||||||
function TestPage() {
 | 
					function TestPage() {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <>
 | 
				
			||||||
 | 
					            {/*<ShippingWarehouseAutocomplete/>*/}
 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
export type QuickDeal = {
 | 
					export type QuickDeal = {
 | 
				
			||||||
    name: string
 | 
					    name: string;
 | 
				
			||||||
    clientName: string
 | 
					    clientName: string;
 | 
				
			||||||
    clientAddress: string
 | 
					    clientAddress: string;
 | 
				
			||||||
    comment:string
 | 
					    comment: string;
 | 
				
			||||||
    acceptanceDate: Date
 | 
					    acceptanceDate: Date;
 | 
				
			||||||
 | 
					    shippingWarehouse: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user