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