feat: generation of modules from the server, moved modules fields from the general tab
This commit is contained in:
3
generateModules.sh
Executable file
3
generateModules.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
sudo npx tsc ./src/modules/modulesFileGen/modulesFileGen.ts
|
||||||
|
mv -f ./src/modules/modulesFileGen/modulesFileGen.js ./src/modules/modulesFileGen/modulesFileGen.cjs
|
||||||
|
sudo node ./src/modules/modulesFileGen/modulesFileGen.cjs
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
"@types/eslint__js": "^8.42.3",
|
"@types/eslint__js": "^8.42.3",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/lodash": "^4.17.7",
|
"@types/lodash": "^4.17.7",
|
||||||
|
"@types/node": "^22.13.9",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
"@typescript-eslint/eslint-plugin": "^7.16.1",
|
||||||
|
|||||||
@@ -300,6 +300,9 @@ export type { ProductGenerateBarcodeResponse } from './models/ProductGenerateBar
|
|||||||
export type { ProductGetBarcodeImageResponse } from './models/ProductGetBarcodeImageResponse';
|
export type { ProductGetBarcodeImageResponse } from './models/ProductGetBarcodeImageResponse';
|
||||||
export type { ProductGetResponse } from './models/ProductGetResponse';
|
export type { ProductGetResponse } from './models/ProductGetResponse';
|
||||||
export type { ProductImageSchema } from './models/ProductImageSchema';
|
export type { ProductImageSchema } from './models/ProductImageSchema';
|
||||||
|
export type { ProductsAndServicesGeneralInfoRequest } from './models/ProductsAndServicesGeneralInfoRequest';
|
||||||
|
export type { ProductsAndServicesGeneralInfoResponse } from './models/ProductsAndServicesGeneralInfoResponse';
|
||||||
|
export type { ProductsAndServicesGeneralInfoSchema } from './models/ProductsAndServicesGeneralInfoSchema';
|
||||||
export type { ProductSchema } from './models/ProductSchema';
|
export type { ProductSchema } from './models/ProductSchema';
|
||||||
export type { ProductUpdateRequest } from './models/ProductUpdateRequest';
|
export type { ProductUpdateRequest } from './models/ProductUpdateRequest';
|
||||||
export type { ProductUpdateResponse } from './models/ProductUpdateResponse';
|
export type { ProductUpdateResponse } from './models/ProductUpdateResponse';
|
||||||
@@ -357,6 +360,10 @@ export type { UpdateBoardOrderRequest } from './models/UpdateBoardOrderRequest';
|
|||||||
export type { UpdateBoardOrderResponse } from './models/UpdateBoardOrderResponse';
|
export type { UpdateBoardOrderResponse } from './models/UpdateBoardOrderResponse';
|
||||||
export type { UpdateBoardRequest } from './models/UpdateBoardRequest';
|
export type { UpdateBoardRequest } from './models/UpdateBoardRequest';
|
||||||
export type { UpdateBoardResponse } from './models/UpdateBoardResponse';
|
export type { UpdateBoardResponse } from './models/UpdateBoardResponse';
|
||||||
|
export type { UpdateCardClientRequest } from './models/UpdateCardClientRequest';
|
||||||
|
export type { UpdateCardClientResponse } from './models/UpdateCardClientResponse';
|
||||||
|
export type { UpdateCardManagerRequest } from './models/UpdateCardManagerRequest';
|
||||||
|
export type { UpdateCardManagerResponse } from './models/UpdateCardManagerResponse';
|
||||||
export type { UpdateDepartmentRequest } from './models/UpdateDepartmentRequest';
|
export type { UpdateDepartmentRequest } from './models/UpdateDepartmentRequest';
|
||||||
export type { UpdateDepartmentResponse } from './models/UpdateDepartmentResponse';
|
export type { UpdateDepartmentResponse } from './models/UpdateDepartmentResponse';
|
||||||
export type { UpdateDepartmentSectionRequest } from './models/UpdateDepartmentSectionRequest';
|
export type { UpdateDepartmentSectionRequest } from './models/UpdateDepartmentSectionRequest';
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ export type CardGeneralInfoSchema = {
|
|||||||
isDeleted: boolean;
|
isDeleted: boolean;
|
||||||
isCompleted: boolean;
|
isCompleted: boolean;
|
||||||
comment: string;
|
comment: string;
|
||||||
shippingWarehouse?: (string | null);
|
|
||||||
manager?: (UserSchema | null);
|
manager?: (UserSchema | null);
|
||||||
boardId: number;
|
boardId: number;
|
||||||
statusId: number;
|
statusId: number;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type ModuleSchema = {
|
|||||||
id: number;
|
id: number;
|
||||||
key: string;
|
key: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
iconName?: (string | null);
|
||||||
isDeleted: boolean;
|
isDeleted: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
10
src/client/models/ProductsAndServicesGeneralInfoRequest.ts
Normal file
10
src/client/models/ProductsAndServicesGeneralInfoRequest.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type { ProductsAndServicesGeneralInfoSchema } from './ProductsAndServicesGeneralInfoSchema';
|
||||||
|
export type ProductsAndServicesGeneralInfoRequest = {
|
||||||
|
cardId: number;
|
||||||
|
data: ProductsAndServicesGeneralInfoSchema;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type ProductsAndServicesGeneralInfoResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type ProductsAndServicesGeneralInfoSchema = {
|
||||||
|
shippingWarehouse?: (string | null);
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/UpdateCardClientRequest.ts
Normal file
9
src/client/models/UpdateCardClientRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type UpdateCardClientRequest = {
|
||||||
|
cardId: number;
|
||||||
|
clientId: number;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/UpdateCardClientResponse.ts
Normal file
9
src/client/models/UpdateCardClientResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type UpdateCardClientResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/UpdateCardManagerRequest.ts
Normal file
9
src/client/models/UpdateCardManagerRequest.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type UpdateCardManagerRequest = {
|
||||||
|
cardId: number;
|
||||||
|
managerId: (number | null);
|
||||||
|
};
|
||||||
|
|
||||||
9
src/client/models/UpdateCardManagerResponse.ts
Normal file
9
src/client/models/UpdateCardManagerResponse.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* generated using openapi-typescript-codegen -- do not edit */
|
||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type UpdateCardManagerResponse = {
|
||||||
|
ok: boolean;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -59,6 +59,12 @@ import type { GetCardProductsBarcodesPdfResponse } from '../models/GetCardProduc
|
|||||||
import type { ManageEmployeeRequest } from '../models/ManageEmployeeRequest';
|
import type { ManageEmployeeRequest } from '../models/ManageEmployeeRequest';
|
||||||
import type { ManageEmployeeResponse } from '../models/ManageEmployeeResponse';
|
import type { ManageEmployeeResponse } from '../models/ManageEmployeeResponse';
|
||||||
import type { ParseCardsExcelResponse } from '../models/ParseCardsExcelResponse';
|
import type { ParseCardsExcelResponse } from '../models/ParseCardsExcelResponse';
|
||||||
|
import type { ProductsAndServicesGeneralInfoRequest } from '../models/ProductsAndServicesGeneralInfoRequest';
|
||||||
|
import type { ProductsAndServicesGeneralInfoResponse } from '../models/ProductsAndServicesGeneralInfoResponse';
|
||||||
|
import type { UpdateCardClientRequest } from '../models/UpdateCardClientRequest';
|
||||||
|
import type { UpdateCardClientResponse } from '../models/UpdateCardClientResponse';
|
||||||
|
import type { UpdateCardManagerRequest } from '../models/UpdateCardManagerRequest';
|
||||||
|
import type { UpdateCardManagerResponse } from '../models/UpdateCardManagerResponse';
|
||||||
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';
|
||||||
@@ -236,6 +242,66 @@ export class CardService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Update Products And Services General Info
|
||||||
|
* @returns ProductsAndServicesGeneralInfoResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static updateProductsAndServicesGeneralInfo({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: ProductsAndServicesGeneralInfoRequest,
|
||||||
|
}): CancelablePromise<ProductsAndServicesGeneralInfoResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/card/update-products-and-services-general-info',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Update Card Manager
|
||||||
|
* @returns UpdateCardManagerResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static updateCardManager({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: UpdateCardManagerRequest,
|
||||||
|
}): CancelablePromise<UpdateCardManagerResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/card/update-card-manager',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Update Card Client
|
||||||
|
* @returns UpdateCardClientResponse Successful Response
|
||||||
|
* @throws ApiError
|
||||||
|
*/
|
||||||
|
public static updateCardClient({
|
||||||
|
requestBody,
|
||||||
|
}: {
|
||||||
|
requestBody: UpdateCardClientRequest,
|
||||||
|
}): CancelablePromise<UpdateCardClientResponse> {
|
||||||
|
return __request(OpenAPI, {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/card/update-card-client',
|
||||||
|
body: requestBody,
|
||||||
|
mediaType: 'application/json',
|
||||||
|
errors: {
|
||||||
|
422: `Validation Error`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Add Kit To Card
|
* Add Kit To Card
|
||||||
* @returns CardAddKitResponse Successful Response
|
* @returns CardAddKitResponse Successful Response
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { UseFormReturnType } from "@mantine/form";
|
|||||||
import { rem, Stack } from "@mantine/core";
|
import { rem, Stack } from "@mantine/core";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import CardAttributeField from "./components/CardAttributeField.tsx";
|
import CardAttributeField from "./components/CardAttributeField.tsx";
|
||||||
import { CardGeneralFormType } from "../../pages/CardsPage/tabs/GeneralTab/GeneralTab.tsx";
|
import { CardGeneralFormType } from "../../pages/CardsPage/drawers/CardEditDrawer/tabs/GeneralTab/GeneralTab.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
project: ProjectSchema;
|
project: ProjectSchema;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { AttributeSchema } from "../../../client";
|
|||||||
import { Checkbox, Group, NumberInput, TextInput, Tooltip } from "@mantine/core";
|
import { Checkbox, Group, NumberInput, TextInput, Tooltip } from "@mantine/core";
|
||||||
import { UseFormReturnType } from "@mantine/form";
|
import { UseFormReturnType } from "@mantine/form";
|
||||||
import { DatePickerInput, DateTimePicker } from "@mantine/dates";
|
import { DatePickerInput, DateTimePicker } from "@mantine/dates";
|
||||||
import { CardGeneralFormType } from "../../../pages/CardsPage/tabs/GeneralTab/GeneralTab.tsx";
|
import { CardGeneralFormType } from "../../../pages/CardsPage/drawers/CardEditDrawer/tabs/GeneralTab/GeneralTab.tsx";
|
||||||
import { IconInfoCircle } from "@tabler/icons-react";
|
import { IconInfoCircle } from "@tabler/icons-react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ type SelectProps = Omit<ObjectSelectProps<StatusSchema | null>, "data" | "getLab
|
|||||||
|
|
||||||
type Props = OtherProps & SelectProps;
|
type Props = OtherProps & SelectProps;
|
||||||
|
|
||||||
const DealStatusSelect: FC<Props> = ({ board, ...props}) => {
|
const CardStatusSelect: FC<Props> = ({ board, ...props}) => {
|
||||||
const [isInitial, setIsInitial] = useState<boolean>(true);
|
const [isInitial, setIsInitial] = useState<boolean>(true);
|
||||||
|
|
||||||
const filteredData = board?.statuses.filter(
|
const filteredData = board?.statuses.filter(
|
||||||
@@ -37,4 +37,4 @@ const DealStatusSelect: FC<Props> = ({ board, ...props}) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default DealStatusSelect;
|
export default CardStatusSelect;
|
||||||
@@ -5,6 +5,8 @@ import { Flex, rem, Text, TextInput, useMantineColorScheme } from "@mantine/core
|
|||||||
import { IconGripHorizontal } from "@tabler/icons-react";
|
import { IconGripHorizontal } from "@tabler/icons-react";
|
||||||
import { useDebouncedValue } from "@mantine/hooks";
|
import { useDebouncedValue } from "@mantine/hooks";
|
||||||
import { notifications } from "../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../shared/lib/notifications.ts";
|
||||||
|
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
||||||
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
cards: CardSummary[];
|
cards: CardSummary[];
|
||||||
@@ -15,6 +17,9 @@ export const CardGroupView: FC<Props> = ({ cards, group }) => {
|
|||||||
const theme = useMantineColorScheme();
|
const theme = useMantineColorScheme();
|
||||||
const [name, setName] = useState<string>(group.name || "");
|
const [name, setName] = useState<string>(group.name || "");
|
||||||
const [debouncedName] = useDebouncedValue(name, 200);
|
const [debouncedName] = useDebouncedValue(name, 200);
|
||||||
|
const { selectedProject } = useProjectsContext();
|
||||||
|
const isServicesAndProductsIncluded = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject);
|
||||||
|
|
||||||
const totalPrice = useMemo(() => cards.reduce((acc, card) => acc + card.totalPrice, 0), [cards]);
|
const totalPrice = useMemo(() => cards.reduce((acc, card) => acc + card.totalPrice, 0), [cards]);
|
||||||
const totalProducts = useMemo(() => cards.reduce((acc, card) => acc + card.totalProducts, 0), [cards]);
|
const totalProducts = useMemo(() => cards.reduce((acc, card) => acc + card.totalProducts, 0), [cards]);
|
||||||
const updateName = () => {
|
const updateName = () => {
|
||||||
@@ -70,19 +75,21 @@ export const CardGroupView: FC<Props> = ({ cards, group }) => {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex
|
{isServicesAndProductsIncluded && (
|
||||||
p={rem(10)}
|
<Flex
|
||||||
direction={"column"}
|
p={rem(10)}
|
||||||
bg={theme.colorScheme === "dark" ? "var(--mantine-color-dark-6)" : "var(--mantine-color-gray-2)"}
|
direction={"column"}
|
||||||
style={{ borderRadius: "0.5rem" }}
|
bg={theme.colorScheme === "dark" ? "var(--mantine-color-dark-6)" : "var(--mantine-color-gray-2)"}
|
||||||
>
|
style={{ borderRadius: "0.5rem" }}
|
||||||
<Text
|
>
|
||||||
c={"gray.6"}
|
<Text
|
||||||
size={"xs"}>Сумма: {totalPrice.toLocaleString("ru-RU")} руб.</Text>
|
c={"gray.6"}
|
||||||
<Text
|
size={"xs"}>Сумма: {totalPrice.toLocaleString("ru-RU")} руб.</Text>
|
||||||
c={"gray.6"}
|
<Text
|
||||||
size={"xs"}>Всего товаров: {totalProducts.toLocaleString("ru-RU")} шт.</Text>
|
c={"gray.6"}
|
||||||
</Flex>
|
size={"xs"}>Всего товаров: {totalProducts.toLocaleString("ru-RU")} шт.</Text>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -9,7 +9,7 @@ import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
|||||||
import { IconCheck, IconLayoutGridRemove, IconTrash } from "@tabler/icons-react";
|
import { IconCheck, IconLayoutGridRemove, IconTrash } from "@tabler/icons-react";
|
||||||
import { useContextMenu } from "mantine-contextmenu";
|
import { useContextMenu } from "mantine-contextmenu";
|
||||||
import useCardSummaryState from "./useCardSummaryState.tsx";
|
import useCardSummaryState from "./useCardSummaryState.tsx";
|
||||||
import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { groupBy, has, uniq } from "lodash";
|
|||||||
import { CardGroupView } from "../CardGroupView/CardGroupView.tsx";
|
import { CardGroupView } from "../CardGroupView/CardGroupView.tsx";
|
||||||
import CreateDealsFromFileButton from "../CreateCardsFromFileButton/CreateDealsFromFileButton.tsx";
|
import CreateDealsFromFileButton from "../CreateCardsFromFileButton/CreateDealsFromFileButton.tsx";
|
||||||
import DragState from "../../../../pages/CardsPage/enums/DragState.ts";
|
import DragState from "../../../../pages/CardsPage/enums/DragState.ts";
|
||||||
import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { CardService, StatusSchema } from "../../../../client";
|
|||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import { dateWithoutTimezone } from "../../../../shared/lib/date.ts";
|
import { dateWithoutTimezone } from "../../../../shared/lib/date.ts";
|
||||||
import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx";
|
import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx";
|
||||||
import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import ShippingWarehouseAutocomplete
|
|||||||
from "../../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
|
from "../../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
|
||||||
import BaseMarketplaceSelect from "../../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
import BaseMarketplaceSelect from "../../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
||||||
import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx";
|
import { usePrefillCardContext } from "../../../../pages/CardsPage/contexts/PrefillCardContext.tsx";
|
||||||
import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import DragState from "../../../../pages/CardsPage/enums/DragState.ts";
|
|||||||
import { useContextMenu } from "mantine-contextmenu";
|
import { useContextMenu } from "mantine-contextmenu";
|
||||||
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
||||||
import useStatus from "./hooks/useStatus.tsx";
|
import useStatus from "./hooks/useStatus.tsx";
|
||||||
import isModuleInProject, { Modules } from "../../../../pages/CardsPage/utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ type Props = Omit<
|
|||||||
ObjectSelectProps<UserSchema | null>,
|
ObjectSelectProps<UserSchema | null>,
|
||||||
"data" | "getValueFn" | "getLabelFn"
|
"data" | "getValueFn" | "getLabelFn"
|
||||||
>;
|
>;
|
||||||
const UserSelect: FC<Props> = props => {
|
const ManagerSelect: FC<Props> = props => {
|
||||||
const { objects: managers } = useManagersList();
|
const { objects: managers } = useManagersList();
|
||||||
return (
|
return (
|
||||||
<ObjectSelect
|
<ObjectSelect
|
||||||
@@ -21,4 +21,4 @@ const UserSelect: FC<Props> = props => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default UserSelect;
|
export default ManagerSelect;
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ type Props = {
|
|||||||
withLabel?: boolean;
|
withLabel?: boolean;
|
||||||
error?: string;
|
error?: string;
|
||||||
inputContainer?: (children: ReactNode) => ReactNode;
|
inputContainer?: (children: ReactNode) => ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
const ClientSelect: FC<Props> = ({ value, onChange, error, inputContainer, withLabel = false }) => {
|
const ClientSelect: FC<Props> = ({ value, onChange, error, inputContainer, withLabel = false, disabled = false }) => {
|
||||||
const { clients } = useClientsList();
|
const { clients } = useClientsList();
|
||||||
const options = clients.map(client => ({
|
const options = clients.map(client => ({
|
||||||
label: client.name,
|
label: client.name,
|
||||||
@@ -37,6 +38,7 @@ const ClientSelect: FC<Props> = ({ value, onChange, error, inputContainer, withL
|
|||||||
label={withLabel && "Клиент"}
|
label={withLabel && "Клиент"}
|
||||||
error={error}
|
error={error}
|
||||||
inputContainer={inputContainer}
|
inputContainer={inputContainer}
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function usePollingEffect(
|
|||||||
): void {
|
): void {
|
||||||
const { interval = 3000, isActive = true, onCleanUp = () => {} } = options;
|
const { interval = 3000, isActive = true, onCleanUp = () => {} } = options;
|
||||||
|
|
||||||
const timeoutIdRef = useRef<number | null>(null);
|
const timeoutIdRef = useRef<NodeJS.Timeout | number | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isActive) {
|
if (!isActive) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { modals } from "./modals/modals.ts";
|
|||||||
import TasksProvider from "./providers/TasksProvider/TasksProvider.tsx";
|
import TasksProvider from "./providers/TasksProvider/TasksProvider.tsx";
|
||||||
import { ContextMenuProvider } from "mantine-contextmenu";
|
import { ContextMenuProvider } from "mantine-contextmenu";
|
||||||
import { ProjectsContextProvider } from "./contexts/ProjectsContext.tsx";
|
import { ProjectsContextProvider } from "./contexts/ProjectsContext.tsx";
|
||||||
|
import { ModulesContextProvider } from "./modules/context/ModulesContext.tsx";
|
||||||
|
|
||||||
// Configuring router
|
// Configuring router
|
||||||
const router = createRouter({ routeTree });
|
const router = createRouter({ routeTree });
|
||||||
@@ -56,8 +57,10 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
<DatesProvider settings={{ locale: "ru" }}>
|
<DatesProvider settings={{ locale: "ru" }}>
|
||||||
<TasksProvider>
|
<TasksProvider>
|
||||||
<ProjectsContextProvider>
|
<ProjectsContextProvider>
|
||||||
<RouterProvider router={router} />
|
<ModulesContextProvider>
|
||||||
<Notifications />
|
<RouterProvider router={router} />
|
||||||
|
<Notifications />
|
||||||
|
</ModulesContextProvider>
|
||||||
</ProjectsContextProvider>
|
</ProjectsContextProvider>
|
||||||
</TasksProvider>
|
</TasksProvider>
|
||||||
</DatesProvider>
|
</DatesProvider>
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import CreateServiceCategoryModal from "../pages/ServicesPage/modals/CreateServi
|
|||||||
import CreateServiceModal from "../pages/ServicesPage/modals/CreateServiceModal.tsx";
|
import CreateServiceModal from "../pages/ServicesPage/modals/CreateServiceModal.tsx";
|
||||||
import createProductModal from "../pages/ProductsPage/modals/CreateProductModal/CreateProductModal.tsx";
|
import createProductModal from "../pages/ProductsPage/modals/CreateProductModal/CreateProductModal.tsx";
|
||||||
import ProductFormModal from "../pages/ClientsPage/modals/ClientFormModal/ClientFormModal.tsx";
|
import ProductFormModal from "../pages/ClientsPage/modals/ClientFormModal/ClientFormModal.tsx";
|
||||||
import AddCardServiceModal from "../pages/CardsPage/modals/AddCardServiceModal.tsx";
|
import AddCardServiceModal from "../modules/cardModules/cardEditorTabs/ProductAndServiceTab/modals/AddCardServiceModal.tsx";
|
||||||
import AddCardProductModal from "../pages/CardsPage/modals/AddCardProductModal.tsx";
|
import AddCardProductModal from "../modules/cardModules/cardEditorTabs/ProductAndServiceTab/modals/AddCardProductModal.tsx";
|
||||||
import PrintBarcodeModal from "./PrintBarcodeModal/PrintBarcodeModal.tsx";
|
import PrintBarcodeModal from "./PrintBarcodeModal/PrintBarcodeModal.tsx";
|
||||||
import AddBarcodeModal from "./AddBarcodeModal/AddBarcodeModal.tsx";
|
import AddBarcodeModal from "./AddBarcodeModal/AddBarcodeModal.tsx";
|
||||||
import BarcodeTemplateFormModal
|
import BarcodeTemplateFormModal
|
||||||
from "../pages/BarcodePage/modals/BarcodeTemplateFormModal/BarcodeTemplateFormModal.tsx";
|
from "../pages/BarcodePage/modals/BarcodeTemplateFormModal/BarcodeTemplateFormModal.tsx";
|
||||||
import ProductServiceFormModal from "../pages/CardsPage/modals/ProductServiceFormModal.tsx";
|
import ProductServiceFormModal from "../modules/cardModules/cardEditorTabs/ProductAndServiceTab/modals/ProductServiceFormModal.tsx";
|
||||||
import UserFormModal from "../pages/AdminPage/modals/UserFormModal/UserFormModal.tsx";
|
import UserFormModal from "../pages/AdminPage/modals/UserFormModal/UserFormModal.tsx";
|
||||||
import EmployeeSelectModal from "./EmployeeSelectModal/EmployeeSelectModal.tsx";
|
import EmployeeSelectModal from "./EmployeeSelectModal/EmployeeSelectModal.tsx";
|
||||||
import EmployeeTableModal from "./EmployeeTableModal/EmployeeTableModal.tsx";
|
import EmployeeTableModal from "./EmployeeTableModal/EmployeeTableModal.tsx";
|
||||||
@@ -24,11 +24,11 @@ import MarketplaceFormModal from "../pages/MarketplacesPage/modals/MarketplaceFo
|
|||||||
import ScanningModal from "./ScanningModal/ScanningModal.tsx";
|
import ScanningModal from "./ScanningModal/ScanningModal.tsx";
|
||||||
import TransactionFormModal from "../pages/AdminPage/tabs/Transactions/modals/TransactionFormModal.tsx";
|
import TransactionFormModal from "../pages/AdminPage/tabs/Transactions/modals/TransactionFormModal.tsx";
|
||||||
import TransactionTagsModal from "../pages/AdminPage/tabs/Transactions/modals/TransactionTagsModal.tsx";
|
import TransactionTagsModal from "../pages/AdminPage/tabs/Transactions/modals/TransactionTagsModal.tsx";
|
||||||
import ShippingProductModal from "../pages/CardsPage/tabs/ShippingTab/modals/ShippingProductModal.tsx";
|
import ShippingProductModal from "../modules/cardModules/cardEditorTabs/ShippingTab/modals/ShippingProductModal.tsx";
|
||||||
import DepartmentModal from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/DepartmentModal.tsx";
|
import DepartmentModal from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/DepartmentModal.tsx";
|
||||||
import AddUserToDepartmentModal
|
import AddUserToDepartmentModal
|
||||||
from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/AddUserToDepartmentModal.tsx";
|
from "../pages/AdminPage/tabs/OrganizationalStructureTab/modals/AddUserToDepartmentModal.tsx";
|
||||||
import AssignEmployeeModal from "../pages/CardsPage/tabs/EmployeesTab/modals/AssignEmployeeModal.tsx";
|
import AssignEmployeeModal from "../modules/cardModules/cardEditorTabs/EmployeesTab/modals/AssignEmployeeModal.tsx";
|
||||||
import ResidualProductModal from "../pages/ResiduesPage/modals/ResidualProductModal/ResidualProductModal.tsx";
|
import ResidualProductModal from "../pages/ResiduesPage/modals/ResidualProductModal/ResidualProductModal.tsx";
|
||||||
import NewReceiptModal from "../pages/ReceiptPage/components/NewReceipt/modals/NewReceiptModal.tsx";
|
import NewReceiptModal from "../pages/ReceiptPage/components/NewReceipt/modals/NewReceiptModal.tsx";
|
||||||
import ReceiptModal from "../pages/ReceiptPage/components/ReceiptEditing/modals/ReceiptModal.tsx";
|
import ReceiptModal from "../pages/ReceiptPage/components/ReceiptEditing/modals/ReceiptModal.tsx";
|
||||||
|
|||||||
147
src/modules/cardModules/cardEditorTabs/ClientTab/ClientTab.tsx
Normal file
147
src/modules/cardModules/cardEditorTabs/ClientTab/ClientTab.tsx
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import { Button, Fieldset, Group, rem, Stack, Textarea, TextInput } from "@mantine/core";
|
||||||
|
import { useCardPageContext } from "../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import { CardService, ClientSchema, ClientService } from "../../../../client";
|
||||||
|
import { notifications } from "../../../../shared/lib/notifications.ts";
|
||||||
|
import ClientSelect from "../../../../components/Selects/ClientSelect/ClientSelect.tsx";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import InlineButton from "../../../../components/InlineButton/InlineButton.tsx";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
|
const ClientTab = () => {
|
||||||
|
const { selectedCard: card, refetchCard } = useCardPageContext();
|
||||||
|
const [initialValues, setInitialValues] = useState<Partial<ClientSchema>>(card?.client ?? {});
|
||||||
|
|
||||||
|
const [client, setClient] = useState<ClientSchema | undefined>(card?.client ?? undefined);
|
||||||
|
|
||||||
|
const form = useForm<Partial<ClientSchema>>(
|
||||||
|
{
|
||||||
|
initialValues,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const data = card?.client ?? {};
|
||||||
|
setInitialValues(data);
|
||||||
|
form.setValues(data);
|
||||||
|
}, [card]);
|
||||||
|
|
||||||
|
const isEditorDisabled = () => client?.id !== card?.client?.id;
|
||||||
|
|
||||||
|
const handleSubmitClientInfo = (values: ClientSchema) => {
|
||||||
|
ClientService.updateClient({
|
||||||
|
requestBody: {
|
||||||
|
data: values,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(({ ok, message }) => {
|
||||||
|
if (!ok) {
|
||||||
|
notifications.error({ message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refetchCard();
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectClient = () => {
|
||||||
|
if (!(card && client)) return;
|
||||||
|
|
||||||
|
CardService.updateCardClient({
|
||||||
|
requestBody: {
|
||||||
|
cardId: card?.id,
|
||||||
|
clientId: client?.id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(({ ok, message }) => {
|
||||||
|
if (!ok) {
|
||||||
|
notifications.error({ message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refetchCard();
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
const clientDataEditor = (
|
||||||
|
<Fieldset legend={"Данные клиента"} flex={1}>
|
||||||
|
<form
|
||||||
|
onSubmit={
|
||||||
|
form.onSubmit(values => handleSubmitClientInfo(values as ClientSchema))
|
||||||
|
}>
|
||||||
|
<Stack gap={rem(10)}>
|
||||||
|
<TextInput
|
||||||
|
disabled
|
||||||
|
placeholder={"Название"}
|
||||||
|
label={"Название"}
|
||||||
|
value={card?.client?.name}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
disabled={isEditorDisabled()}
|
||||||
|
placeholder={"Введите телефон"}
|
||||||
|
label={"Телефон клиента"}
|
||||||
|
{...form.getInputProps("details.phoneNumber")}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
disabled={isEditorDisabled()}
|
||||||
|
placeholder={"Введите email"}
|
||||||
|
label={"Email"}
|
||||||
|
{...form.getInputProps("details.email")}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
disabled={isEditorDisabled()}
|
||||||
|
placeholder={"Введите телеграм"}
|
||||||
|
label={"Телеграм"}
|
||||||
|
{...form.getInputProps("details.telegram")}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
disabled={isEditorDisabled()}
|
||||||
|
placeholder={"Введите ИНН"}
|
||||||
|
label={"ИНН"}
|
||||||
|
{...form.getInputProps("details.inn")}
|
||||||
|
/>
|
||||||
|
<Textarea
|
||||||
|
disabled={isEditorDisabled()}
|
||||||
|
placeholder={"Введите комментарий"}
|
||||||
|
label={"Комментарий"}
|
||||||
|
{...form.getInputProps("comment")}
|
||||||
|
/>
|
||||||
|
<Group>
|
||||||
|
<Button
|
||||||
|
variant={"default"}
|
||||||
|
disabled={isEditorDisabled() || isEqual(initialValues, form.values)}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</form>
|
||||||
|
</Fieldset>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack flex={1}>
|
||||||
|
<Fieldset legend={"Выбор клиента"} flex={1}>
|
||||||
|
<Stack gap={rem(10)}>
|
||||||
|
<ClientSelect
|
||||||
|
value={client}
|
||||||
|
onChange={setClient}
|
||||||
|
withLabel
|
||||||
|
disabled={!isEqual(initialValues, form.values)}
|
||||||
|
/>
|
||||||
|
<Group>
|
||||||
|
<InlineButton
|
||||||
|
onClick={handleSelectClient}
|
||||||
|
disabled={!isEditorDisabled()}
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</InlineButton>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Fieldset>
|
||||||
|
{clientDataEditor}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ClientTab;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
|
import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
|
||||||
import useEmployeeTableColumns from "../hooks/useEmployeesTableColumns.tsx";
|
import useEmployeeTableColumns from "../hooks/useEmployeesTableColumns.tsx";
|
||||||
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
|
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
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 { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import { CardEmployeesSchema, CardService } from "../../../../../client";
|
import { CardEmployeesSchema, CardService } from "../../../../../client";
|
||||||
|
|
||||||
const useEmployeesTab = () => {
|
const useEmployeesTab = () => {
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { Button, Fieldset, Group, rem, Stack } from "@mantine/core";
|
||||||
|
import { useCardPageContext } from "../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import { CardSchema, CardService, type UserSchema } from "../../../../client";
|
||||||
|
import { notifications } from "../../../../shared/lib/notifications.ts";
|
||||||
|
import ManagerSelect from "../../../../components/ManagerSelect/ManagerSelect.tsx";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
|
type ManagerForm = {
|
||||||
|
manager?: (UserSchema | null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ManagerTab = () => {
|
||||||
|
const { selectedCard: card, refetchCard } = useCardPageContext();
|
||||||
|
const [initialValues, setInitialValues] = useState<ManagerForm>(card as CardSchema);
|
||||||
|
|
||||||
|
const form = useForm<ManagerForm>({
|
||||||
|
initialValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const data = card ?? {};
|
||||||
|
setInitialValues(data);
|
||||||
|
form.setValues(data);
|
||||||
|
}, [card]);
|
||||||
|
|
||||||
|
const onSubmit = async (values: ManagerForm) => {
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
return CardService.updateCardManager({
|
||||||
|
requestBody: {
|
||||||
|
cardId: card.id,
|
||||||
|
managerId: values.manager?.id ?? null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(({ ok, message }) => {
|
||||||
|
if (!ok) {
|
||||||
|
notifications.error({ message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refetchCard();
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={form.onSubmit(values => onSubmit(values))}>
|
||||||
|
<Fieldset flex={1}>
|
||||||
|
<Stack gap={rem(10)}>
|
||||||
|
<ManagerSelect
|
||||||
|
placeholder={"Укажите менеджера"}
|
||||||
|
label={"Менеджер"}
|
||||||
|
{...form.getInputProps("manager")}
|
||||||
|
/>
|
||||||
|
<Group>
|
||||||
|
<Button
|
||||||
|
type={"submit"}
|
||||||
|
variant={"default"}
|
||||||
|
disabled={isEqual(initialValues, form.values)}
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Fieldset>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ManagerTab;
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.products-list {
|
.products-list {
|
||||||
width: 60%;
|
width: 52%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: rem(10);
|
gap: rem(10);
|
||||||
@@ -1,16 +1,8 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import styles from "./ProductAndServiceTab.module.css";
|
import styles from "./ProductAndServiceTab.module.css";
|
||||||
import ProductView from "./components/ProductView/ProductView.tsx";
|
import ProductView from "./components/ProductView/ProductView.tsx";
|
||||||
import {
|
import { Button, Checkbox, Divider, Flex, Group, rem, ScrollArea, Stack, Text, Title } from "@mantine/core";
|
||||||
Button,
|
import CardServicesTable from "./components/CardServicesTable/CardServicesTable.tsx";
|
||||||
Divider,
|
|
||||||
Flex,
|
|
||||||
rem,
|
|
||||||
ScrollArea,
|
|
||||||
Text,
|
|
||||||
Title,
|
|
||||||
} from "@mantine/core";
|
|
||||||
import CardServicesTable from "./components/DealServicesTable/CardServicesTable.tsx";
|
|
||||||
import useCardProductAndServiceTabState from "./hooks/useProductAndServiceTabState.tsx";
|
import useCardProductAndServiceTabState from "./hooks/useProductAndServiceTabState.tsx";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import {
|
import {
|
||||||
@@ -22,17 +14,19 @@ import {
|
|||||||
ProductService,
|
ProductService,
|
||||||
} from "../../../../client";
|
} from "../../../../client";
|
||||||
import { notifications } from "../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../shared/lib/notifications.ts";
|
||||||
import { CreateProductRequest } from "../../../ProductsPage/types.ts";
|
import { CreateProductRequest } from "../../../../pages/ProductsPage/types.ts";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import GeneralDataForm from "./components/GeneralDataForm/GeneralDataForm.tsx";
|
||||||
|
import PrintDealBarcodesButton from "./components/PrintDealBarcodesButton/PrintDealBarcodesButton.tsx";
|
||||||
|
import PaymentLinkButton from "./components/PaymentLinkButton/PaymentLinkButton.tsx";
|
||||||
|
|
||||||
const ProductAndServiceTab: FC = () => {
|
const ProductAndServiceTab: FC = () => {
|
||||||
const { cardState, cardServicesState, cardProductsState } =
|
const { cardState, cardServicesState, cardProductsState } = useCardProductAndServiceTabState();
|
||||||
useCardProductAndServiceTabState();
|
|
||||||
const isLocked = Boolean(cardState.card?.billRequest || cardState.card?.group?.billRequest);
|
const isLocked = Boolean(cardState.card?.billRequest || cardState.card?.group?.billRequest);
|
||||||
const onAddProductClick = () => {
|
const onAddProductClick = () => {
|
||||||
if (!cardProductsState.onCreate || !cardState.card || !cardState.card.clientId) return;
|
if (!cardProductsState.onCreate || !cardState.card || !cardState.card.clientId) return;
|
||||||
const productIds = cardState.card.products.map(
|
const productIds = cardState.card.products.map(
|
||||||
product => product.product.id
|
product => product.product.id,
|
||||||
);
|
);
|
||||||
modals.openContextModal({
|
modals.openContextModal({
|
||||||
modal: "addCardProduct",
|
modal: "addCardProduct",
|
||||||
@@ -51,26 +45,26 @@ const ProductAndServiceTab: FC = () => {
|
|||||||
acc +
|
acc +
|
||||||
row.services.reduce(
|
row.services.reduce(
|
||||||
(acc2, row2) => acc2 + row2.price * row.quantity,
|
(acc2, row2) => acc2 + row2.price * row.quantity,
|
||||||
0
|
0,
|
||||||
),
|
),
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
const cardServicesPrice = cardState.card.services.reduce(
|
const cardServicesPrice = cardState.card.services.reduce(
|
||||||
(acc, row) => acc + row.price * row.quantity,
|
(acc, row) => acc + row.price * row.quantity,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
return cardServicesPrice + productServicesPrice;
|
return cardServicesPrice + productServicesPrice;
|
||||||
};
|
};
|
||||||
const onCopyServices = (
|
const onCopyServices = (
|
||||||
sourceProduct: CardProductSchema,
|
sourceProduct: CardProductSchema,
|
||||||
destinationProducts: CardProductSchema[]
|
destinationProducts: CardProductSchema[],
|
||||||
) => {
|
) => {
|
||||||
if (!cardState.card) return;
|
if (!cardState.card) return;
|
||||||
CardService.copyProductServices({
|
CardService.copyProductServices({
|
||||||
requestBody: {
|
requestBody: {
|
||||||
cardId: cardState.card.id,
|
cardId: cardState.card.id,
|
||||||
destinationProductIds: destinationProducts.map(
|
destinationProductIds: destinationProducts.map(
|
||||||
product => product.product.id
|
product => product.product.id,
|
||||||
),
|
),
|
||||||
sourceProductId: sourceProduct.product.id,
|
sourceProductId: sourceProduct.product.id,
|
||||||
},
|
},
|
||||||
@@ -147,7 +141,7 @@ const ProductAndServiceTab: FC = () => {
|
|||||||
notifications.guess(ok, { message });
|
notifications.guess(ok, { message });
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
await cardState.refetch();
|
await cardState.refetch();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -212,11 +206,12 @@ const ProductAndServiceTab: FC = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
styles["container"],
|
styles["container"],
|
||||||
cardState.card?.billRequest && styles["container-disabled"]
|
cardState.card?.billRequest && styles["container-disabled"],
|
||||||
)}>
|
)}>
|
||||||
<div className={styles["products-list"]}>
|
<div className={styles["products-list"]}>
|
||||||
<ScrollArea offsetScrollbars>
|
<ScrollArea offsetScrollbars>
|
||||||
@@ -235,6 +230,27 @@ const ProductAndServiceTab: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles["card-container"]}>
|
<div className={styles["card-container"]}>
|
||||||
|
{cardState.card && (
|
||||||
|
<Group
|
||||||
|
className={styles["card-container-wrapper"]}
|
||||||
|
justify={"space-between"}
|
||||||
|
wrap={"nowrap"}
|
||||||
|
mr={"xs"}
|
||||||
|
>
|
||||||
|
<Group wrap={"nowrap"}>
|
||||||
|
<PrintDealBarcodesButton card={cardState.card} />
|
||||||
|
<Checkbox
|
||||||
|
label={"Оплачен"}
|
||||||
|
checked={cardState.card.billRequest?.paid || cardState.card.group?.billRequest?.paid || false}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<PaymentLinkButton card={cardState.card} />
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
<Stack className={styles["card-container-wrapper"]} mr={"xs"}>
|
||||||
|
<GeneralDataForm />
|
||||||
|
</Stack>
|
||||||
<ScrollArea offsetScrollbars>
|
<ScrollArea offsetScrollbars>
|
||||||
<Flex
|
<Flex
|
||||||
direction={"column"}
|
direction={"column"}
|
||||||
@@ -5,7 +5,7 @@ import { ActionIcon, Button, Flex, Modal, NumberInput, rem, Text, Title, Tooltip
|
|||||||
import { IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
import { IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { isNumber } from "lodash";
|
import { isNumber } from "lodash";
|
||||||
import SimpleUsersTable from "../../../../components/SimpleUsersTable/SimpleUsersTable.tsx";
|
import SimpleUsersTable from "../../../../../../pages/CardsPage/components/SimpleUsersTable/SimpleUsersTable.tsx";
|
||||||
import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../../../../redux/store.ts";
|
import { RootState } from "../../../../../../redux/store.ts";
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import ShippingWarehouseAutocomplete
|
||||||
|
from "../../../../../../components/Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
|
||||||
|
import { CardService, ShippingWarehouseSchema } from "../../../../../../client";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import { useCardPageContext } from "../../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
|
import { Button, Checkbox, Stack } from "@mantine/core";
|
||||||
|
import { notifications } from "../../../../../../shared/lib/notifications.ts";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
|
|
||||||
|
type GeneralDataFormType = {
|
||||||
|
shippingWarehouse?: ShippingWarehouseSchema | null | string;
|
||||||
|
isServicesProfitAccounted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GeneralDataForm = () => {
|
||||||
|
const { selectedCard: card, refetchCard } = useCardPageContext();
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const [initialValues, setInitialValues] = useState<GeneralDataFormType>(card);
|
||||||
|
|
||||||
|
const form = useForm<GeneralDataFormType>({
|
||||||
|
initialValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const data = card ?? {};
|
||||||
|
setInitialValues(data);
|
||||||
|
form.setValues(data);
|
||||||
|
}, [card]);
|
||||||
|
|
||||||
|
const isShippingWarehouse = (
|
||||||
|
value: ShippingWarehouseSchema | string | null | undefined,
|
||||||
|
): value is ShippingWarehouseSchema => {
|
||||||
|
return !!value && !["string"].includes(typeof value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (values: GeneralDataFormType) => {
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const shippingWarehouse = isShippingWarehouse(values.shippingWarehouse)
|
||||||
|
? values.shippingWarehouse.name
|
||||||
|
: values.shippingWarehouse;
|
||||||
|
|
||||||
|
CardService.updateProductsAndServicesGeneralInfo({
|
||||||
|
requestBody: {
|
||||||
|
cardId: card.id,
|
||||||
|
data: {
|
||||||
|
...values,
|
||||||
|
shippingWarehouse,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(({ ok, message }) => {
|
||||||
|
if (!ok) {
|
||||||
|
notifications.error({ message });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refetchCard();
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={form.onSubmit(values => onSubmit(values))}>
|
||||||
|
<Stack>
|
||||||
|
<ShippingWarehouseAutocomplete
|
||||||
|
placeholder={"Введите склад отгрузки"}
|
||||||
|
label={"Склад отгрузки"}
|
||||||
|
value={
|
||||||
|
isShippingWarehouse(
|
||||||
|
form.values.shippingWarehouse,
|
||||||
|
)
|
||||||
|
? form.values.shippingWarehouse
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onChange={event => {
|
||||||
|
if (isShippingWarehouse(event)) {
|
||||||
|
form.getInputProps(
|
||||||
|
"shippingWarehouse",
|
||||||
|
).onChange(event.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
form.getInputProps(
|
||||||
|
"shippingWarehouse",
|
||||||
|
).onChange(event);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={"Учет выручки в статистике"}
|
||||||
|
{...form.getInputProps("isServicesProfitAccounted", { type: "checkbox" })}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type={"submit"}
|
||||||
|
variant={"default"}
|
||||||
|
disabled={isEqual(initialValues, form.values)}
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GeneralDataForm;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { CardSchema } from "../../../../../client";
|
import { CardSchema } from "../../../../../../client";
|
||||||
import ButtonCopy from "../../../../../components/ButtonCopy/ButtonCopy.tsx";
|
import ButtonCopy from "../../../../../../components/ButtonCopy/ButtonCopy.tsx";
|
||||||
import { ButtonCopyControlled } from "../../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx";
|
import { ButtonCopyControlled } from "../../../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx";
|
||||||
import { getCurrentDateTimeForFilename } from "../../../../../shared/lib/date.ts";
|
import { getCurrentDateTimeForFilename } from "../../../../../../shared/lib/date.ts";
|
||||||
import FileSaver from "file-saver";
|
import FileSaver from "file-saver";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ActionIcon, Tooltip } from "@mantine/core";
|
import { ActionIcon, Group, Tooltip } from "@mantine/core";
|
||||||
import styles from "../../../ui/CardsPage.module.css";
|
import styles from "../../../../../../pages/CardsPage/ui/CardsPage.module.css";
|
||||||
import { CardSchema, CardService } from "../../../../../client";
|
import { CardSchema, CardService } from "../../../../../../client";
|
||||||
import { base64ToBlob } from "../../../../../shared/lib/utils.ts";
|
import { base64ToBlob } from "../../../../../../shared/lib/utils.ts";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../../shared/lib/notifications.ts";
|
||||||
import { IconBarcode, IconPrinter } from "@tabler/icons-react";
|
import { IconBarcode, IconPrinter } from "@tabler/icons-react";
|
||||||
|
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ type Props = {
|
|||||||
|
|
||||||
const PrintDealBarcodesButton = ({ card }: Props) => {
|
const PrintDealBarcodesButton = ({ card }: Props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Group wrap={"nowrap"}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
className={styles["print-deals-button"]}
|
className={styles["print-deals-button"]}
|
||||||
label={"Распечатать штрихкоды сделки"}
|
label={"Распечатать штрихкоды сделки"}
|
||||||
@@ -56,7 +56,7 @@ const PrintDealBarcodesButton = ({ card }: Props) => {
|
|||||||
<IconPrinter />
|
<IconPrinter />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>
|
</Group>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ import { MRT_TableOptions } from "mantine-react-table";
|
|||||||
import { ActionIcon, Button, Flex, Modal, rem, Tooltip } from "@mantine/core";
|
import { ActionIcon, Button, Flex, Modal, rem, Tooltip } from "@mantine/core";
|
||||||
import { IconEdit, IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
import { IconEdit, IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import SimpleUsersTable from "../../../../components/SimpleUsersTable/SimpleUsersTable.tsx";
|
import SimpleUsersTable from "../../../../../../pages/CardsPage/components/SimpleUsersTable/SimpleUsersTable.tsx";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../../../../redux/store.ts";
|
import { RootState } from "../../../../../../redux/store.ts";
|
||||||
import useCardProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
import useCardProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { CRUDTableProps } from "../../../../../types/CRUDTable.tsx";
|
import { CRUDTableProps } from "../../../../../types/CRUDTable.tsx";
|
||||||
import { CardService, CardServiceSchema, CardProductSchema } from "../../../../../client";
|
import { CardService, CardServiceSchema, CardProductSchema } from "../../../../../client";
|
||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
|
|
||||||
const useCardState = () => {
|
const useCardState = () => {
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ContextModalProps } from "@mantine/modals";
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
} from "../../../../../pages/ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||||
import { CardProductSchema, CardProductServiceSchema } from "../../../client";
|
import { CardProductSchema, CardProductServiceSchema } from "../../../../../client";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import { NumberInput } from "@mantine/core";
|
import { NumberInput } from "@mantine/core";
|
||||||
import ProductSelect from "../../../components/ProductSelect/ProductSelect.tsx";
|
import ProductSelect from "../../../../../components/ProductSelect/ProductSelect.tsx";
|
||||||
import { omit } from "lodash";
|
import { omit } from "lodash";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { ContextModalProps } from "@mantine/modals";
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
import BaseFormModal, { CreateEditFormProps } from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
import BaseFormModal, { CreateEditFormProps } from "../../../../../pages/ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||||
import { CardServiceSchema } from "../../../client";
|
import { CardServiceSchema } from "../../../../../client";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import { ComboboxItem, ComboboxItemGroup, NumberInput, OptionsFilter } from "@mantine/core";
|
import { ComboboxItem, ComboboxItemGroup, NumberInput, OptionsFilter } from "@mantine/core";
|
||||||
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
import ServiceWithPriceInput from "../../../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
||||||
import { ServiceType } from "../../../shared/enums/ServiceType.ts";
|
import { ServiceType } from "../../../../../shared/enums/ServiceType.ts";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../redux/store.ts";
|
import { RootState } from "../../../../../redux/store.ts";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
serviceIds?: number[];
|
serviceIds?: number[];
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import BaseFormModal, {
|
import BaseFormModal, {
|
||||||
CreateEditFormProps,
|
CreateEditFormProps,
|
||||||
} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
} from "../../../../../pages/ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||||
import {
|
import {
|
||||||
CardProductServiceSchema,
|
CardProductServiceSchema,
|
||||||
ServiceSchema,
|
ServiceSchema,
|
||||||
} from "../../../client";
|
} from "../../../../../client";
|
||||||
import { ContextModalProps } from "@mantine/modals";
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
import { useForm, UseFormReturnType } from "@mantine/form";
|
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||||
import { isNil, isNumber } from "lodash";
|
import { isNil, isNumber } from "lodash";
|
||||||
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
import ServiceWithPriceInput from "../../../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
||||||
import { Checkbox, Flex, rem } from "@mantine/core";
|
import { Checkbox, Flex, rem } from "@mantine/core";
|
||||||
import { ServiceType } from "../../../shared/enums/ServiceType.ts";
|
import { ServiceType } from "../../../../../shared/enums/ServiceType.ts";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { RootState } from "../../../redux/store.ts";
|
import { RootState } from "../../../../../redux/store.ts";
|
||||||
|
|
||||||
type RestProps = {
|
type RestProps = {
|
||||||
quantity: number;
|
quantity: number;
|
||||||
@@ -8,7 +8,7 @@ import classes from "../ShippingTab.module.css";
|
|||||||
import "mantine-datatable/styles.css";
|
import "mantine-datatable/styles.css";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
||||||
import { Group, rem, Text } from "@mantine/core";
|
import { Flex, rem, Text } from "@mantine/core";
|
||||||
import { ShippingProductParentData } from "../types/ShippingProductData.tsx";
|
import { ShippingProductParentData } from "../types/ShippingProductData.tsx";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import InlineShippingButton from "./InlineShippingButton.tsx";
|
import InlineShippingButton from "./InlineShippingButton.tsx";
|
||||||
@@ -63,15 +63,15 @@ const BoxesTable = ({ items, onCreateShippingProduct }: Props) => {
|
|||||||
|
|
||||||
const getBoxActions = (box: BoxSchema) => {
|
const getBoxActions = (box: BoxSchema) => {
|
||||||
return (
|
return (
|
||||||
<Group wrap={"nowrap"} gap={rem(10)}>
|
<Flex wrap={"nowrap"} direction={"row-reverse"} gap={rem(10)}>
|
||||||
|
<InlineShippingButton onClick={() => onDeleteBoxClick(box)}>
|
||||||
|
<IconTrash />
|
||||||
|
</InlineShippingButton>
|
||||||
<InlineShippingButton onClick={() => onCreateShippingProduct({ boxId: box.id })}>
|
<InlineShippingButton onClick={() => onCreateShippingProduct({ boxId: box.id })}>
|
||||||
<IconPlus />
|
<IconPlus />
|
||||||
Товар
|
Товар
|
||||||
</InlineShippingButton>
|
</InlineShippingButton>
|
||||||
<InlineShippingButton onClick={() => onDeleteBoxClick(box)}>
|
</Flex>
|
||||||
<IconTrash />
|
|
||||||
</InlineShippingButton>
|
|
||||||
</Group>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import { Flex, rem, Stack } from "@mantine/core";
|
import { Flex, rem, Stack } from "@mantine/core";
|
||||||
import { BoxSchema, PalletSchema, ShippingProductSchema } from "../../../../../client";
|
import { BoxSchema, PalletSchema, ShippingProductSchema } from "../../../../../client";
|
||||||
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
||||||
@@ -5,7 +5,7 @@ import { IconEdit, IconTrash } from "@tabler/icons-react";
|
|||||||
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 useUpdateCard from "./useUpdateCard.tsx";
|
import useUpdateCard from "./useUpdateCard.tsx";
|
||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
|
|
||||||
const useShippingTableColumns = () => {
|
const useShippingTableColumns = () => {
|
||||||
const { update } = useUpdateCard();
|
const { update } = useUpdateCard();
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import {
|
import {
|
||||||
CreateBoxInCardSchema,
|
CreateBoxInCardSchema,
|
||||||
CreateBoxInPalletSchema, PalletSchema,
|
CreateBoxInPalletSchema, PalletSchema,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
|
|
||||||
|
|
||||||
const useShippingQrs = () => {
|
const useShippingQrs = () => {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../../pages/CardsPage/contexts/CardPageContext.tsx";
|
||||||
import { CardService } from "../../../../../client";
|
import { CardService } from "../../../../../client";
|
||||||
|
|
||||||
const useUpdateCard = () => {
|
const useUpdateCard = () => {
|
||||||
20
src/modules/connectModules.tsx
Normal file
20
src/modules/connectModules.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { ModuleNames } from "./modules.tsx";
|
||||||
|
import ClientTab from "./cardModules/cardEditorTabs/ClientTab/ClientTab.tsx";
|
||||||
|
import ModulesType from "./types.tsx";
|
||||||
|
import ProductAndServiceTab from "./cardModules/cardEditorTabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
|
||||||
|
import EmployeesTab from "./cardModules/cardEditorTabs/EmployeesTab/EmployeesTab.tsx";
|
||||||
|
import ShippingTab from "./cardModules/cardEditorTabs/ShippingTab/ShippingTab.tsx";
|
||||||
|
import ManagerTab from "./cardModules/cardEditorTabs/ManagersTab/ManagersTab.tsx";
|
||||||
|
|
||||||
|
const connectModules = (modules: ModulesType) => {
|
||||||
|
|
||||||
|
modules[ModuleNames.CLIENTS].tab = <ClientTab />;
|
||||||
|
modules[ModuleNames.SERVICES_AND_PRODUCTS].tab = <ProductAndServiceTab />;
|
||||||
|
modules[ModuleNames.EMPLOYEES].tab = <EmployeesTab />;
|
||||||
|
modules[ModuleNames.SHIPMENT].tab = <ShippingTab />;
|
||||||
|
modules[ModuleNames.MANAGERS].tab = <ManagerTab />;
|
||||||
|
|
||||||
|
return modules;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connectModules;
|
||||||
54
src/modules/context/ModulesContext.tsx
Normal file
54
src/modules/context/ModulesContext.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import React, { createContext, FC, useContext, useEffect, useState } from "react";
|
||||||
|
import { useProjectsContext } from "../../contexts/ProjectsContext.tsx";
|
||||||
|
import { MODULES } from "../modules.tsx";
|
||||||
|
import { Module } from "../types.tsx";
|
||||||
|
|
||||||
|
type ModulesContextState = {
|
||||||
|
modules: Module[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModulesContext = createContext<ModulesContextState | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
|
const useModulesContextState = () => {
|
||||||
|
const { selectedProject } = useProjectsContext();
|
||||||
|
|
||||||
|
const [modules, setModules] = useState<Module[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const modules = selectedProject?.modules ?? [];
|
||||||
|
const projectModules = modules.map(module => {
|
||||||
|
return MODULES[module.key];
|
||||||
|
}) ?? [];
|
||||||
|
setModules(projectModules);
|
||||||
|
}, [selectedProject?.id]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
modules,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type CardPageContextProviderProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ModulesContextProvider: FC<CardPageContextProviderProps> = ({ children }) => {
|
||||||
|
const state = useModulesContextState();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModulesContext.Provider value={state}>
|
||||||
|
{children}
|
||||||
|
</ModulesContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useModulesContext = () => {
|
||||||
|
const context = useContext(ModulesContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
"useModulesContext must be used within a ModulesContextProvider",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
21
src/modules/modules.tsx
Normal file
21
src/modules/modules.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { IconUser, IconBox, IconCubeSend, IconUsersGroup, IconUserCog } from "@tabler/icons-react"
|
||||||
|
import ModulesType from "./types.tsx";
|
||||||
|
import connectModules from "./connectModules.tsx";
|
||||||
|
|
||||||
|
export enum ModuleNames {
|
||||||
|
CLIENTS = "clients",
|
||||||
|
SERVICES_AND_PRODUCTS = "servicesAndProducts",
|
||||||
|
SHIPMENT = "shipment",
|
||||||
|
EMPLOYEES = "employees",
|
||||||
|
MANAGERS = "managers"
|
||||||
|
}
|
||||||
|
|
||||||
|
const modules: ModulesType = {
|
||||||
|
[ModuleNames.CLIENTS]: { info: { label: "Клиенты", key: "clients", icon: <IconUser /> } },
|
||||||
|
[ModuleNames.SERVICES_AND_PRODUCTS]: { info: { label: "Товары и услуги", key: "servicesAndProducts", icon: <IconBox /> } },
|
||||||
|
[ModuleNames.SHIPMENT]: { info: { label: "Отгрузка", key: "shipment", icon: <IconCubeSend /> } },
|
||||||
|
[ModuleNames.EMPLOYEES]: { info: { label: "Сотрудники", key: "employees", icon: <IconUsersGroup /> } },
|
||||||
|
[ModuleNames.MANAGERS]: { info: { label: "Менеджер", key: "managers", icon: <IconUserCog /> } }
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MODULES = connectModules(modules);
|
||||||
61
src/modules/modulesFileGen/modulesFileGen.cjs
Normal file
61
src/modules/modulesFileGen/modulesFileGen.cjs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var axios_1 = require("axios");
|
||||||
|
var fs = require("fs");
|
||||||
|
// endregion
|
||||||
|
var OUTPUT_FILE = "./src/modules/modules.tsx";
|
||||||
|
function camelToConstCase(camelStr) {
|
||||||
|
return camelStr
|
||||||
|
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
||||||
|
.toUpperCase();
|
||||||
|
}
|
||||||
|
var writeToFile = function (data) {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(OUTPUT_FILE, data.trim());
|
||||||
|
console.log("File successfully generated.");
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var getImports = function (modules) {
|
||||||
|
var prefix = "import { ";
|
||||||
|
var postfix = " } from \"@tabler/icons-react\"\n" +
|
||||||
|
"import ModulesType from \"./types.tsx\";\n" +
|
||||||
|
"import connectModules from \"./connectModules.tsx\";";
|
||||||
|
var filteredModules = modules.filter(function (module) { return module.iconName; });
|
||||||
|
var icons = filteredModules.map(function (module) { return module.iconName; }).join(", ");
|
||||||
|
return prefix + icons + postfix;
|
||||||
|
};
|
||||||
|
var getModuleNames = function (modules) {
|
||||||
|
return modules.map(function (module) {
|
||||||
|
return "".concat(camelToConstCase(module.key), " = \"").concat(module.key, "\"");
|
||||||
|
}).join(",\n\t");
|
||||||
|
};
|
||||||
|
var getModules = function (modules) {
|
||||||
|
return modules.map(function (module) {
|
||||||
|
var iconStr = "null";
|
||||||
|
if (module.iconName) {
|
||||||
|
iconStr = "<" + module.iconName + " />";
|
||||||
|
}
|
||||||
|
return "[ModuleNames.".concat(camelToConstCase(module.key), "]: { info: { label: \"").concat(module.label, "\", key: \"").concat(module.key, "\", icon: ").concat(iconStr, " } }");
|
||||||
|
}).join(",\n\t");
|
||||||
|
};
|
||||||
|
var generateRows = function (modules) {
|
||||||
|
var imports = getImports(modules);
|
||||||
|
var moduleNames = "\n\nexport enum ModuleNames {\n\t".concat(getModuleNames(modules), "\n}\n");
|
||||||
|
var modulesStr = "\nconst modules: ModulesType = {\n\t".concat(getModules(modules), "\n};\n");
|
||||||
|
var connectModules = "\nexport const MODULES = connectModules(modules);";
|
||||||
|
var result = imports + moduleNames + modulesStr + connectModules;
|
||||||
|
writeToFile(result);
|
||||||
|
};
|
||||||
|
var modulesFileGen = function () {
|
||||||
|
console.log("Start file generation...");
|
||||||
|
axios_1.default
|
||||||
|
.get("http://127.0.0.1:8000/project/modules")
|
||||||
|
.then(function (response) {
|
||||||
|
generateRows(response.data.modules);
|
||||||
|
})
|
||||||
|
.catch(function (err) { return console.log(err); });
|
||||||
|
};
|
||||||
|
modulesFileGen();
|
||||||
86
src/modules/modulesFileGen/modulesFileGen.ts
Normal file
86
src/modules/modulesFileGen/modulesFileGen.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import axios, { AxiosResponse } from "axios";
|
||||||
|
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
// region Types
|
||||||
|
type Module = {
|
||||||
|
id: number;
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
iconName?: string;
|
||||||
|
isDeleted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModulesResponse = {
|
||||||
|
modules: Module[];
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
const OUTPUT_FILE = "./src/modules/modules.tsx";
|
||||||
|
|
||||||
|
function camelToConstCase(camelStr: string): string {
|
||||||
|
return camelStr
|
||||||
|
.replace(/([a-z])([A-Z])/g, "$1_$2")
|
||||||
|
.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeToFile = (data: string) => {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(OUTPUT_FILE, data.trim());
|
||||||
|
console.log("File successfully generated.");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getImports = (modules: Module[]): string => {
|
||||||
|
const prefix = "import { ";
|
||||||
|
const postfix = " } from \"@tabler/icons-react\"\n" +
|
||||||
|
"import ModulesType from \"./types.tsx\";\n" +
|
||||||
|
"import connectModules from \"./connectModules.tsx\";";
|
||||||
|
|
||||||
|
const filteredModules = modules.filter(module => module.iconName);
|
||||||
|
const icons = filteredModules.map((module: Module) => module.iconName).join(", ");
|
||||||
|
|
||||||
|
return prefix + icons + postfix;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getModuleNames = (modules: Module[]) => {
|
||||||
|
return modules.map(module => {
|
||||||
|
return `${camelToConstCase(module.key)} = "${module.key}"`;
|
||||||
|
}).join(",\n\t");
|
||||||
|
};
|
||||||
|
|
||||||
|
const getModules = (modules: Module[]) => {
|
||||||
|
return modules.map(module => {
|
||||||
|
let iconStr = "null";
|
||||||
|
if (module.iconName) {
|
||||||
|
iconStr = "<" + module.iconName + " />";
|
||||||
|
}
|
||||||
|
return `[ModuleNames.${camelToConstCase(module.key)}]: { info: { label: "${module.label}", key: "${module.key}", icon: ${iconStr} } }`;
|
||||||
|
}).join(",\n\t");
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateRows = (modules: Module[]) => {
|
||||||
|
const imports = getImports(modules);
|
||||||
|
|
||||||
|
const moduleNames = `\n\nexport enum ModuleNames {\n\t${getModuleNames(modules)}\n}\n`;
|
||||||
|
const modulesStr = `\nconst modules: ModulesType = {\n\t${getModules(modules)}\n};\n`;
|
||||||
|
const connectModules = "\nexport const MODULES = connectModules(modules);";
|
||||||
|
const result: string = imports + moduleNames + modulesStr + connectModules;
|
||||||
|
|
||||||
|
writeToFile(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
const modulesFileGen = () => {
|
||||||
|
console.log("Start file generation...");
|
||||||
|
|
||||||
|
axios
|
||||||
|
.get("http://127.0.0.1:8000/project/modules")
|
||||||
|
.then((response: AxiosResponse<ModulesResponse>) => {
|
||||||
|
generateRows(response.data.modules);
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
modulesFileGen();
|
||||||
16
src/modules/types.tsx
Normal file
16
src/modules/types.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
export type Module = {
|
||||||
|
info: {
|
||||||
|
label: string;
|
||||||
|
key: string;
|
||||||
|
icon: ReactNode;
|
||||||
|
},
|
||||||
|
tab?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Modules = {
|
||||||
|
[key: string]: Module;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Modules;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ProjectSchema } from "../../../client";
|
import { ProjectSchema } from "../../client";
|
||||||
|
|
||||||
export enum Modules {
|
export enum Modules {
|
||||||
SERVICES_AND_PRODUCTS = "servicesAndProducts",
|
SERVICES_AND_PRODUCTS = "servicesAndProducts",
|
||||||
@@ -6,7 +6,6 @@ export enum Modules {
|
|||||||
EMPLOYEES = "employees",
|
EMPLOYEES = "employees",
|
||||||
CLIENTS = "clients",
|
CLIENTS = "clients",
|
||||||
MANAGERS = "managers",
|
MANAGERS = "managers",
|
||||||
MEGA_MODULE = "hui",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isModuleInProject = (module: Modules, project?: ProjectSchema | null) => {
|
const isModuleInProject = (module: Modules, project?: ProjectSchema | null) => {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { CardPageContextProvider, useCardPageContext } from "../../CardsPage/contexts/CardPageContext.tsx";
|
import { CardPageContextProvider, useCardPageContext } from "../../CardsPage/contexts/CardPageContext.tsx";
|
||||||
import ProductAndServiceTab from "../../CardsPage/tabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
|
import ProductAndServiceTab from "../../../modules/cardModules/cardEditorTabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
|
||||||
import React, { FC, useEffect } from "react";
|
import React, { FC, useEffect } from "react";
|
||||||
import { CardService } from "../../../client";
|
import { CardService } from "../../../client";
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import { Box, Drawer, rem, Tabs } from "@mantine/core";
|
import { Box, Drawer, rem, Tabs } from "@mantine/core";
|
||||||
import { FC, ReactNode, useEffect } from "react";
|
import { FC, ReactNode, useEffect } from "react";
|
||||||
import { useCardPageContext } from "../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../contexts/CardPageContext.tsx";
|
||||||
import { IconBox, IconCalendarUser, IconCubeSend, IconSettings, IconUser, IconUsersGroup } from "@tabler/icons-react";
|
import { IconCalendarUser, IconSettings } from "@tabler/icons-react";
|
||||||
import CardStatusChangeTable from "../../components/CardStatusChangeTable/CardStatusChangeTable.tsx";
|
import CardStatusChangeTable from "./tabs/CardStatusChangeTable/CardStatusChangeTable.tsx";
|
||||||
import GeneralTab from "../../tabs/GeneralTab/GeneralTab.tsx";
|
import GeneralTab from "./tabs/GeneralTab/GeneralTab.tsx";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import ProductAndServiceTab from "../../tabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import ShippingTab from "../../tabs/ShippingTab/ShippingTab.tsx";
|
import { useModulesContext } from "../../../../modules/context/ModulesContext.tsx";
|
||||||
import EmployeesTab from "../../tabs/EmployeesTab/EmployeesTab.tsx";
|
|
||||||
import ClientTab from "../../tabs/ClientTab/ClientTab.tsx";
|
|
||||||
|
|
||||||
const useCardStatusChangeState = () => {
|
const useCardStatusChangeState = () => {
|
||||||
const { selectedCard } = useCardPageContext();
|
const { selectedCard } = useCardPageContext();
|
||||||
@@ -36,8 +33,7 @@ const CardEditDrawer: FC = () => {
|
|||||||
const { isVisible, onClose } = useCardEditDrawerState();
|
const { isVisible, onClose } = useCardEditDrawerState();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const { selectedCard } = useCardPageContext();
|
const { modules } = useModulesContext();
|
||||||
const modules = new Set<string>(selectedCard?.board.project.modules.map(module => module.key));
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isVisible) return;
|
if (isVisible) return;
|
||||||
@@ -62,23 +58,27 @@ const CardEditDrawer: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTab = (
|
const getTabs = () => {
|
||||||
key: string,
|
const moduleTabs = modules.map(module => (
|
||||||
icon: ReactNode,
|
<Tabs.Tab
|
||||||
label: string,
|
value={module.info.key}
|
||||||
enablingModules: string[] | null = null, // Show if at least one of modules is in project
|
leftSection={module.info.icon}
|
||||||
) => {
|
>
|
||||||
if (!enablingModules) {
|
{module.info.label}
|
||||||
enablingModules = [key];
|
</Tabs.Tab>
|
||||||
}
|
));
|
||||||
if (!enablingModules.some(key => modules.has(key))) return;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs.Tab
|
<>{moduleTabs}</>
|
||||||
value={key}
|
);
|
||||||
leftSection={icon}>
|
};
|
||||||
{label}
|
|
||||||
</Tabs.Tab>
|
const getTabPanels = () => {
|
||||||
|
const moduleTabPanels = modules.map(
|
||||||
|
module => getTabPanel(module.info.key, module.tab),
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>{moduleTabPanels}</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,18 +115,12 @@ const CardEditDrawer: FC = () => {
|
|||||||
leftSection={<IconCalendarUser />}>
|
leftSection={<IconCalendarUser />}>
|
||||||
История
|
История
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
{getTab("clients", <IconUser />, "Клиент", ["servicesAndProducts", "clients"])}
|
{getTabs()}
|
||||||
{getTab("servicesAndProducts", <IconBox />, "Товары и услуги")}
|
|
||||||
{getTab("shipment", <IconCubeSend />, "Отгрузка")}
|
|
||||||
{getTab("employees", <IconUsersGroup />, "Исполнители")}
|
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
|
|
||||||
{getTabPanel("general", <GeneralTab />)}
|
{getTabPanel("general", <GeneralTab />)}
|
||||||
{getTabPanel("clients", <ClientTab />)}
|
|
||||||
{getTabPanel("history", <CardEditDrawerStatusChangeTable />)}
|
{getTabPanel("history", <CardEditDrawerStatusChangeTable />)}
|
||||||
{getTabPanel("servicesAndProducts", <ProductAndServiceTab />)}
|
{getTabPanels()}
|
||||||
{getTabPanel("shipment", <ShippingTab />)}
|
|
||||||
{getTabPanel("employees", <EmployeesTab />)}
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { CardStatusHistorySchema } from "../../../../client";
|
import { CardStatusHistorySchema } from "../../../../../../client";
|
||||||
import { useDealStatusChangeTableColumns } from "./columns.tsx";
|
import { useDealStatusChangeTableColumns } from "./columns.tsx";
|
||||||
import { BaseTable } from "../../../../components/BaseTable/BaseTable.tsx";
|
import { BaseTable } from "../../../../../../components/BaseTable/BaseTable.tsx";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -1,6 +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 { CardStatusHistorySchema } from "../../../../client";
|
import { CardStatusHistorySchema } from "../../../../../../client";
|
||||||
import { Spoiler, Text } from "@mantine/core";
|
import { Spoiler, Text } from "@mantine/core";
|
||||||
|
|
||||||
export const useDealStatusChangeTableColumns = () => {
|
export const useDealStatusChangeTableColumns = () => {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { useCardPageContext } from "../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../../contexts/CardPageContext.tsx";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
@@ -14,31 +14,17 @@ import {
|
|||||||
TextInput,
|
TextInput,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import {
|
import { CardSchema, CardService, ClientService, ProjectSchema, StatusSchema } from "../../../../../../client";
|
||||||
CardSchema,
|
|
||||||
CardService,
|
|
||||||
ClientService,
|
|
||||||
ProjectSchema,
|
|
||||||
ShippingWarehouseSchema,
|
|
||||||
StatusSchema,
|
|
||||||
} from "../../../../client";
|
|
||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import { notifications } from "../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../../shared/lib/notifications.ts";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import ShippingWarehouseAutocomplete
|
import { ButtonCopyControlled } from "../../../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx";
|
||||||
from "../../../../components/Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
|
|
||||||
import { ButtonCopyControlled } from "../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx";
|
|
||||||
import { useClipboard } from "@mantine/hooks";
|
import { useClipboard } from "@mantine/hooks";
|
||||||
import ManagerSelect from "../../../../components/ManagerSelect/ManagerSelect.tsx";
|
import ProjectSelect from "../../../../../../components/ProjectSelect/ProjectSelect.tsx";
|
||||||
import ProjectSelect from "../../../../components/ProjectSelect/ProjectSelect.tsx";
|
import BoardSelect from "../../../../../../components/BoardSelect/BoardSelect.tsx";
|
||||||
import BoardSelect from "../../../../components/BoardSelect/BoardSelect.tsx";
|
import CardStatusSelect from "../../../../../../components/DealStatusSelect/CardStatusSelect.tsx";
|
||||||
import DealStatusSelect from "../../../../components/DealStatusSelect/DealStatusSelect.tsx";
|
import CardAttributeFields from "../../../../../../components/CardAttributeFields/CardAttributeFields.tsx";
|
||||||
import CardAttributeFields from "../../../../components/CardAttributeFields/CardAttributeFields.tsx";
|
import getAttributesFromCard from "../../../../../../components/CardAttributeFields/utils/getAttributesFromCard.ts";
|
||||||
import getAttributesFromCard from "../../../../components/CardAttributeFields/utils/getAttributesFromCard.ts";
|
|
||||||
import isModuleInProject, { Modules } from "../../utils/isModuleInProject.ts";
|
|
||||||
import PaymentLinkButton from "./components/PaymentLinkButton.tsx";
|
|
||||||
import PrintDealBarcodesButton from "./components/PrintDealBarcodesButton.tsx";
|
|
||||||
import ClientSelect from "../../../../components/Selects/ClientSelect/ClientSelect.tsx";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
card: CardSchema;
|
card: CardSchema;
|
||||||
@@ -56,10 +42,6 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [project, setProject] = useState<ProjectSchema | null>(card.board.project);
|
const [project, setProject] = useState<ProjectSchema | null>(card.board.project);
|
||||||
|
|
||||||
const isServicesAndProductsIncluded = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, card.board.project);
|
|
||||||
const isManagerIncluded = isModuleInProject(Modules.MANAGERS, card.board.project);
|
|
||||||
const isClientIncluded = isModuleInProject(Modules.CLIENTS, card.board.project);
|
|
||||||
|
|
||||||
const getInitialValues = (card: CardSchema): CardGeneralFormType => {
|
const getInitialValues = (card: CardSchema): CardGeneralFormType => {
|
||||||
return {
|
return {
|
||||||
...card,
|
...card,
|
||||||
@@ -99,7 +81,6 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
statusId: values.status.id,
|
statusId: values.status.id,
|
||||||
boardId: values.board.id,
|
boardId: values.board.id,
|
||||||
clientId: values.client?.id ?? null,
|
clientId: values.client?.id ?? null,
|
||||||
shippingWarehouse: values.shippingWarehouse?.toString(),
|
|
||||||
attributes,
|
attributes,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -107,7 +88,6 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
notifications.guess(ok, { message });
|
notifications.guess(ok, { message });
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
CardService.getCardById({ cardId: card.id }).then(data => {
|
CardService.getCardById({ cardId: card.id }).then(data => {
|
||||||
console.log(data);
|
|
||||||
setSelectedCard(data);
|
setSelectedCard(data);
|
||||||
initialValues = getInitialValues(data);
|
initialValues = getInitialValues(data);
|
||||||
form.setValues(initialValues);
|
form.setValues(initialValues);
|
||||||
@@ -131,21 +111,7 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
await updateClientInfo(values);
|
await updateClientInfo(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
const shippingWarehouse = isShippingWarehouse(values.shippingWarehouse)
|
await updateCardInfo(values);
|
||||||
? values.shippingWarehouse.name
|
|
||||||
: values.shippingWarehouse;
|
|
||||||
await updateCardInfo(
|
|
||||||
{
|
|
||||||
...values,
|
|
||||||
shippingWarehouse,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isShippingWarehouse = (
|
|
||||||
value: ShippingWarehouseSchema | string | null | undefined,
|
|
||||||
): value is ShippingWarehouseSchema => {
|
|
||||||
return !!value && !["string"].includes(typeof value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCopyGuestUrlClick = () => {
|
const onCopyGuestUrlClick = () => {
|
||||||
@@ -196,7 +162,7 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
{...form.getInputProps("board")}
|
{...form.getInputProps("board")}
|
||||||
label={"Доска"}
|
label={"Доска"}
|
||||||
/>
|
/>
|
||||||
<DealStatusSelect
|
<CardStatusSelect
|
||||||
board={form.values.board}
|
board={form.values.board}
|
||||||
{...form.getInputProps("status")}
|
{...form.getInputProps("status")}
|
||||||
label={"Статус"}
|
label={"Статус"}
|
||||||
@@ -211,49 +177,6 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
placeholder={"Введите коментарий"}
|
placeholder={"Введите коментарий"}
|
||||||
{...form.getInputProps("comment")}
|
{...form.getInputProps("comment")}
|
||||||
/>
|
/>
|
||||||
{isClientIncluded && (
|
|
||||||
<ClientSelect
|
|
||||||
{...form.getInputProps("client")}
|
|
||||||
withLabel
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isServicesAndProductsIncluded && (
|
|
||||||
<ShippingWarehouseAutocomplete
|
|
||||||
placeholder={"Введите склад отгрузки"}
|
|
||||||
label={"Склад отгрузки"}
|
|
||||||
value={
|
|
||||||
isShippingWarehouse(
|
|
||||||
form.values.shippingWarehouse,
|
|
||||||
)
|
|
||||||
? form.values.shippingWarehouse
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onChange={event => {
|
|
||||||
if (isShippingWarehouse(event)) {
|
|
||||||
form.getInputProps(
|
|
||||||
"shippingWarehouse",
|
|
||||||
).onChange(event.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
form.getInputProps(
|
|
||||||
"shippingWarehouse",
|
|
||||||
).onChange(event);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isManagerIncluded && (
|
|
||||||
<ManagerSelect
|
|
||||||
placeholder={"Укажите менеджера"}
|
|
||||||
label={"Менеджер"}
|
|
||||||
{...form.getInputProps("manager")}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isServicesAndProductsIncluded && (
|
|
||||||
<Checkbox
|
|
||||||
label={"Учет выручки с услуг в статистике"}
|
|
||||||
{...form.getInputProps("isServicesProfitAccounted", { type: "checkbox" })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{project && (
|
{project && (
|
||||||
<CardAttributeFields
|
<CardAttributeFields
|
||||||
project={project}
|
project={project}
|
||||||
@@ -273,36 +196,16 @@ const Content: FC<Props> = ({ card }) => {
|
|||||||
align={"center"}
|
align={"center"}
|
||||||
gap={rem(10)}
|
gap={rem(10)}
|
||||||
justify={"center"}>
|
justify={"center"}>
|
||||||
<Flex
|
<ButtonCopyControlled
|
||||||
gap={rem(10)}
|
onCopyClick={onCopyGuestUrlClick}
|
||||||
align={"center"}
|
onCopiedLabel={
|
||||||
justify={"space-between"}>
|
"Ссылка скопирована в буфер обмена"
|
||||||
{isServicesAndProductsIncluded && (
|
}
|
||||||
<PrintDealBarcodesButton card={card} />
|
copied={clipboard.copied}
|
||||||
)}
|
>
|
||||||
<Flex gap={rem(10)}>
|
Ссылка на редактирование
|
||||||
{isServicesAndProductsIncluded && (
|
</ButtonCopyControlled>
|
||||||
<PaymentLinkButton card={card} />
|
|
||||||
)}
|
|
||||||
<ButtonCopyControlled
|
|
||||||
onCopyClick={onCopyGuestUrlClick}
|
|
||||||
onCopiedLabel={
|
|
||||||
"Ссылка скопирована в буфер обмена"
|
|
||||||
}
|
|
||||||
copied={clipboard.copied}
|
|
||||||
>
|
|
||||||
Ссылка на редактирование
|
|
||||||
</ButtonCopyControlled>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex gap={rem(10)}>
|
<Flex gap={rem(10)}>
|
||||||
{isServicesAndProductsIncluded && (
|
|
||||||
<Checkbox
|
|
||||||
label={"Оплачен"}
|
|
||||||
checked={card.billRequest?.paid || card.group?.billRequest?.paid || false}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={"Завершена"}
|
label={"Завершена"}
|
||||||
{...form.getInputProps("isCompleted", { type: "checkbox" })}
|
{...form.getInputProps("isCompleted", { type: "checkbox" })}
|
||||||
@@ -2,7 +2,7 @@ import { FC } from "react";
|
|||||||
import { CardProductSchema, ProductSchema } from "../../../../../../client";
|
import { CardProductSchema, ProductSchema } from "../../../../../../client";
|
||||||
import { Image, rem, Text, Title } from "@mantine/core";
|
import { Image, rem, Text, Title } from "@mantine/core";
|
||||||
import { isNil } from "lodash";
|
import { isNil } from "lodash";
|
||||||
import { ProductFieldNames } from "../../../../tabs/ProductAndServiceTab/components/ProductView/ProductView.tsx";
|
import { ProductFieldNames } from "../../../../../../modules/cardModules/cardEditorTabs/ProductAndServiceTab/components/ProductView/ProductView.tsx";
|
||||||
import ProductServicesTable from "../tables/ProductServicesTable/ProductServicesTable.tsx";
|
import ProductServicesTable from "../tables/ProductServicesTable/ProductServicesTable.tsx";
|
||||||
import styles from "./ProductPreview.module.css";
|
import styles from "./ProductPreview.module.css";
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useForm } from "@mantine/form";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { BaseMarketplaceSchema } from "../../../../../client";
|
import { BaseMarketplaceSchema } from "../../../../../client";
|
||||||
import { useCardSummariesFull } from "../../../hooks/useCardSummaries.tsx";
|
import { useCardSummariesFull } from "../../../hooks/useCardSummaries.tsx";
|
||||||
import isModuleInProject, { Modules } from "../../../utils/isModuleInProject.ts";
|
import isModuleInProject, { Modules } from "../../../../../modules/utils/isModuleInProject.ts";
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
idOrName: string | null;
|
idOrName: string | null;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Flex, Modal, NumberInput, rem } from "@mantine/core";
|
|||||||
import { UseFormReturnType } from "@mantine/form";
|
import { UseFormReturnType } from "@mantine/form";
|
||||||
import { CardsPageState } from "../hooks/useCardsPageState.tsx";
|
import { CardsPageState } from "../hooks/useCardsPageState.tsx";
|
||||||
import ObjectSelect from "../../../components/ObjectSelect/ObjectSelect.tsx";
|
import ObjectSelect from "../../../components/ObjectSelect/ObjectSelect.tsx";
|
||||||
import DealStatusSelect from "../../../components/DealStatusSelect/DealStatusSelect.tsx";
|
import CardStatusSelect from "../../../components/DealStatusSelect/CardStatusSelect.tsx";
|
||||||
import BaseMarketplaceSelect from "../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
import BaseMarketplaceSelect from "../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
||||||
import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx";
|
import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx";
|
||||||
import { useDisclosure } from "@mantine/hooks";
|
import { useDisclosure } from "@mantine/hooks";
|
||||||
@@ -25,7 +25,7 @@ const CardsTableFiltersModal = ({ form, projects }: Props) => {
|
|||||||
<IconFilter />
|
<IconFilter />
|
||||||
Фильтры
|
Фильтры
|
||||||
</InlineButton>
|
</InlineButton>
|
||||||
<Modal title={"Фильтры для сделок"} opened={opened} onClose={close}>
|
<Modal title={"Фильтры"} opened={opened} onClose={close}>
|
||||||
<Flex
|
<Flex
|
||||||
direction={"column"}
|
direction={"column"}
|
||||||
gap={rem(10)}
|
gap={rem(10)}
|
||||||
@@ -49,7 +49,7 @@ const CardsTableFiltersModal = ({ form, projects }: Props) => {
|
|||||||
{...form.getInputProps("board")}
|
{...form.getInputProps("board")}
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<DealStatusSelect
|
<CardStatusSelect
|
||||||
board={form.values.board}
|
board={form.values.board}
|
||||||
{...form.getInputProps("status")}
|
{...form.getInputProps("status")}
|
||||||
clearable
|
clearable
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
import { Button, Fieldset, Flex, rem, Stack, Textarea, TextInput } from "@mantine/core";
|
|
||||||
import { useCardPageContext } from "../../contexts/CardPageContext.tsx";
|
|
||||||
import { useForm } from "@mantine/form";
|
|
||||||
import { CardGeneralFormType } from "../GeneralTab/GeneralTab.tsx";
|
|
||||||
import { CardSchema, CardService, ClientService } from "../../../../client";
|
|
||||||
import { isEqual } from "lodash";
|
|
||||||
import { notifications } from "../../../../shared/lib/notifications.ts";
|
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
const ClientTab = () => {
|
|
||||||
const { selectedCard: card, setSelectedCard } = useCardPageContext();
|
|
||||||
const initialValues: CardGeneralFormType = card as CardSchema;
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
if (!card?.client) return;
|
|
||||||
|
|
||||||
const form = useForm<CardGeneralFormType>(
|
|
||||||
{
|
|
||||||
initialValues: initialValues,
|
|
||||||
validate: {
|
|
||||||
name: (value: string) => value.length > 0 ? null : "Название сделки не может быть пустым",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const hasChanges = !isEqual(form.values, initialValues);
|
|
||||||
const updateClientInfo = async (values: CardGeneralFormType) => {
|
|
||||||
if (!values.client) return;
|
|
||||||
|
|
||||||
return ClientService.updateClient({
|
|
||||||
requestBody: {
|
|
||||||
data: values.client,
|
|
||||||
},
|
|
||||||
}).then(({ ok, message }) => notifications.guess(ok, { message }));
|
|
||||||
};
|
|
||||||
const update = async () => {
|
|
||||||
return CardService.getCardById({ cardId: form.values.id }).then(data => {
|
|
||||||
setSelectedCard(data);
|
|
||||||
form.setInitialValues(data);
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: ["getCardSummaries"],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const handleSave = () => {
|
|
||||||
updateClientInfo(form.values).then(async () => {
|
|
||||||
await update();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
|
||||||
form.setInitialValues(initialValues);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Flex direction={"column"} flex={1} gap={rem(10)}>
|
|
||||||
<Flex flex={1}>
|
|
||||||
<Fieldset legend={"Клиент"} flex={1}>
|
|
||||||
<Stack gap={rem(10)}>
|
|
||||||
<TextInput
|
|
||||||
disabled
|
|
||||||
placeholder={"Название"}
|
|
||||||
label={"Название"}
|
|
||||||
value={card?.client.name}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder={"Введите телефон"}
|
|
||||||
label={"Телефон клиента"}
|
|
||||||
{...form.getInputProps("client.details.phoneNumber")}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder={"Введите email"}
|
|
||||||
label={"Email"}
|
|
||||||
{...form.getInputProps("client.details.email")}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder={"Введите телеграм"}
|
|
||||||
label={"Телеграм"}
|
|
||||||
{...form.getInputProps("client.details.telegram")}
|
|
||||||
/>
|
|
||||||
<TextInput
|
|
||||||
placeholder={"Введите ИНН"}
|
|
||||||
label={"ИНН"}
|
|
||||||
{...form.getInputProps("client.details.inn")}
|
|
||||||
/>
|
|
||||||
<Textarea
|
|
||||||
placeholder={"Введите комментарий"}
|
|
||||||
label={"Комментарий"}
|
|
||||||
{...form.getInputProps("client.comment")}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</Fieldset>
|
|
||||||
</Flex>
|
|
||||||
<Flex
|
|
||||||
gap={rem(10)}
|
|
||||||
justify={"flex-end"}
|
|
||||||
display={!hasChanges ? "none" : "flex"}
|
|
||||||
>
|
|
||||||
<Button onClick={handleCancel} variant={"default"}>Отмена</Button>
|
|
||||||
<Button onClick={handleSave} variant={"default"}>Сохранить</Button>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default ClientTab;
|
|
||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import { ObjectSelectProps } from "../../../../../../components/ObjectSelect/ObjectSelect.tsx";
|
import { ObjectSelectProps } from "../../../../../../components/ObjectSelect/ObjectSelect.tsx";
|
||||||
import BaseMarketplaceSelect
|
import BaseMarketplaceSelect
|
||||||
from "../../../../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
from "../../../../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
||||||
import DealStatusSelect from "../../../../../../components/DealStatusSelect/DealStatusSelect.tsx";
|
import CardStatusSelect from "../../../../../../components/DealStatusSelect/CardStatusSelect.tsx";
|
||||||
import { ProfitTableSegmentedControl } from "../ProfitTableSegmentedControl/ProfitTableSegmentedControl.tsx";
|
import { ProfitTableSegmentedControl } from "../ProfitTableSegmentedControl/ProfitTableSegmentedControl.tsx";
|
||||||
import ManagerSelect from "../../../../../../components/ManagerSelect/ManagerSelect.tsx";
|
import ManagerSelect from "../../../../../../components/ManagerSelect/ManagerSelect.tsx";
|
||||||
import TransactionTagSelect from "../../../../components/ExpenseTagSelect/TransactionTagSelect.tsx";
|
import TransactionTagSelect from "../../../../components/ExpenseTagSelect/TransactionTagSelect.tsx";
|
||||||
@@ -107,7 +107,7 @@ export const Filters = (props: FiltersProps) => {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
{props.statusSelectProps &&
|
{props.statusSelectProps &&
|
||||||
<DealStatusSelect
|
<CardStatusSelect
|
||||||
board={props.boardSelectProps?.value ?? null}
|
board={props.boardSelectProps?.value ?? null}
|
||||||
{...props.statusSelectProps}
|
{...props.statusSelectProps}
|
||||||
clearable
|
clearable
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* prettier-ignore-start */
|
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
|
||||||
// This file is auto-generated by TanStack Router
|
// This file was automatically generated by TanStack Router.
|
||||||
|
// You should NOT make any changes in this file as it will be overwritten.
|
||||||
|
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||||
|
|
||||||
import { createFileRoute } from '@tanstack/react-router'
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
|
||||||
@@ -36,16 +36,19 @@ const IndexLazyImport = createFileRoute('/')()
|
|||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
|
|
||||||
const TestLazyRoute = TestLazyImport.update({
|
const TestLazyRoute = TestLazyImport.update({
|
||||||
|
id: '/test',
|
||||||
path: '/test',
|
path: '/test',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/test.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/test.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const StatisticsLazyRoute = StatisticsLazyImport.update({
|
const StatisticsLazyRoute = StatisticsLazyImport.update({
|
||||||
|
id: '/statistics',
|
||||||
path: '/statistics',
|
path: '/statistics',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/statistics.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/statistics.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const ShippingwarehousesLazyRoute = ShippingwarehousesLazyImport.update({
|
const ShippingwarehousesLazyRoute = ShippingwarehousesLazyImport.update({
|
||||||
|
id: '/shipping_warehouses',
|
||||||
path: '/shipping_warehouses',
|
path: '/shipping_warehouses',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() =>
|
} as any).lazy(() =>
|
||||||
@@ -53,66 +56,79 @@ const ShippingwarehousesLazyRoute = ShippingwarehousesLazyImport.update({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const ServicesLazyRoute = ServicesLazyImport.update({
|
const ServicesLazyRoute = ServicesLazyImport.update({
|
||||||
|
id: '/services',
|
||||||
path: '/services',
|
path: '/services',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/services.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/services.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const ResiduesLazyRoute = ResiduesLazyImport.update({
|
const ResiduesLazyRoute = ResiduesLazyImport.update({
|
||||||
|
id: '/residues',
|
||||||
path: '/residues',
|
path: '/residues',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/residues.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/residues.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const ReceiptLazyRoute = ReceiptLazyImport.update({
|
const ReceiptLazyRoute = ReceiptLazyImport.update({
|
||||||
|
id: '/receipt',
|
||||||
path: '/receipt',
|
path: '/receipt',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/receipt.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/receipt.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const ProductsLazyRoute = ProductsLazyImport.update({
|
const ProductsLazyRoute = ProductsLazyImport.update({
|
||||||
|
id: '/products',
|
||||||
path: '/products',
|
path: '/products',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/products.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/products.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const MarketplacesLazyRoute = MarketplacesLazyImport.update({
|
const MarketplacesLazyRoute = MarketplacesLazyImport.update({
|
||||||
|
id: '/marketplaces',
|
||||||
path: '/marketplaces',
|
path: '/marketplaces',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/marketplaces.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/marketplaces.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const LoginLazyRoute = LoginLazyImport.update({
|
const LoginLazyRoute = LoginLazyImport.update({
|
||||||
|
id: '/login',
|
||||||
path: '/login',
|
path: '/login',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/login.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/login.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const LeadsLazyRoute = LeadsLazyImport.update({
|
const LeadsLazyRoute = LeadsLazyImport.update({
|
||||||
|
id: '/leads',
|
||||||
path: '/leads',
|
path: '/leads',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/leads.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/leads.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const ClientsLazyRoute = ClientsLazyImport.update({
|
const ClientsLazyRoute = ClientsLazyImport.update({
|
||||||
|
id: '/clients',
|
||||||
path: '/clients',
|
path: '/clients',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/clients.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/clients.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const BarcodeLazyRoute = BarcodeLazyImport.update({
|
const BarcodeLazyRoute = BarcodeLazyImport.update({
|
||||||
|
id: '/barcode',
|
||||||
path: '/barcode',
|
path: '/barcode',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/barcode.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/barcode.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const AdminLazyRoute = AdminLazyImport.update({
|
const AdminLazyRoute = AdminLazyImport.update({
|
||||||
|
id: '/admin',
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/admin.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/admin.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const IndexLazyRoute = IndexLazyImport.update({
|
const IndexLazyRoute = IndexLazyImport.update({
|
||||||
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route))
|
} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route))
|
||||||
|
|
||||||
const LeadsDealIdRoute = LeadsDealIdImport.update({
|
const LeadsDealIdRoute = LeadsDealIdImport.update({
|
||||||
|
id: '/$dealId',
|
||||||
path: '/$dealId',
|
path: '/$dealId',
|
||||||
getParentRoute: () => LeadsLazyRoute,
|
getParentRoute: () => LeadsLazyRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const DealsDealIdRoute = DealsDealIdImport.update({
|
const DealsDealIdRoute = DealsDealIdImport.update({
|
||||||
|
id: '/deals/$dealId',
|
||||||
path: '/deals/$dealId',
|
path: '/deals/$dealId',
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} as any)
|
||||||
@@ -406,8 +422,6 @@ export const routeTree = rootRoute
|
|||||||
._addFileChildren(rootRouteChildren)
|
._addFileChildren(rootRouteChildren)
|
||||||
._addFileTypes<FileRouteTypes>()
|
._addFileTypes<FileRouteTypes>()
|
||||||
|
|
||||||
/* prettier-ignore-end */
|
|
||||||
|
|
||||||
/* ROUTE_MANIFEST_START
|
/* ROUTE_MANIFEST_START
|
||||||
{
|
{
|
||||||
"routes": {
|
"routes": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ProductSchema } from "../client";
|
import { ProductSchema } from "../client";
|
||||||
import { isNil } from "lodash";
|
import { isNil } from "lodash";
|
||||||
import { ProductFieldNames } from "../pages/CardsPage/tabs/ProductAndServiceTab/components/ProductView/ProductView.tsx";
|
import { ProductFieldNames } from "../modules/cardModules/cardEditorTabs/ProductAndServiceTab/components/ProductView/ProductView.tsx";
|
||||||
import UseObjectState from "./UseObjectState.ts";
|
import UseObjectState from "./UseObjectState.ts";
|
||||||
import { CRUDTableProps } from "./CRUDTable.tsx";
|
import { CRUDTableProps } from "./CRUDTable.tsx";
|
||||||
import { MRT_RowData } from "mantine-react-table";
|
import { MRT_RowData } from "mantine-react-table";
|
||||||
|
|||||||
Reference in New Issue
Block a user