From 553e76d6109b98739998fda4e1c11e3cb251bb03 Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Tue, 16 Sep 2025 10:56:10 +0400 Subject: [PATCH] feat: modules, products, services, services kits --- package.json | 5 +- .../desktop/DealsTable/DealsTable.tsx | 3 + .../desktop/TopToolPanel/TopToolPanel.tsx | 2 +- .../CreateBoardButton/CreateBoardButton.tsx | 2 +- .../CreateDealButton/CreateDealButton.tsx | 2 +- .../CreateStatusButton/CreateStatusButton.tsx | 2 +- .../components/shared/DealCard/DealCard.tsx | 3 + .../components/CreateBoardButton.tsx | 5 +- .../DealEditorDrawer/DealEditorDrawer.tsx | 6 +- .../components/DealEditorBody.tsx | 60 +- .../tabs/GeneralTab/GeneralTab.tsx | 2 +- .../GeneralTab/{ => components}/Footer.tsx | 0 .../components/ProjectEditorBody.tsx | 15 +- .../tabs/GeneralTab/GeneralTab.tsx | 6 +- .../GeneralTab/{ => components}/Footer.tsx | 0 .../tabs/ModulesTab/ModulesTab.tsx | 41 + .../ModulesTab/components/ModulesTable.tsx | 32 + .../hooks/useModulesTableColumns.tsx | 24 + .../drawers/ProjectEditorDrawer/tabs/index.ts | 2 + .../components/CreateProjectButton.tsx | 2 +- .../components/CreateStatusButton.tsx | 2 +- .../ObjectMultiSelect/ObjectMultiSelect.tsx | 108 + .../selects/ObjectSelect/ObjectSelect.tsx | 3 + src/components/ui/BaseTable/BaseTable.tsx | 3 +- .../ui/ImageDropzone/ImageDropzone.tsx | 119 ++ src/components/ui/ImageDropzone/types.ts | 12 + .../cruds/baseCrud/getCommonQueryClient.ts | 38 + .../cruds/baseCrud/useCrudOperations.tsx | 136 +- src/hooks/cruds/useBoardsCrud.tsx | 6 +- src/hooks/cruds/useDealsCrud.tsx | 6 +- src/hooks/cruds/useProjectsCrud.tsx | 4 +- src/hooks/cruds/useStatusesCrud.tsx | 6 +- src/lib/client/@tanstack/react-query.gen.ts | 1010 ++++++++++ src/lib/client/sdk.gen.ts | 781 ++++++++ src/lib/client/types.gen.ts | 1740 +++++++++++++++++ src/lib/client/zod.gen.ts | 866 ++++++++ .../base/BaseFormModal/BaseFormModal.tsx | 63 + .../BaseFormModal/BaseFormModalActions.tsx | 25 + src/modals/modals.ts | 12 + src/modules/connectModules.tsx | 13 + .../FulfillmentBaseTab.module.css | 38 + .../FulfillmentBaseTab/FulfillmentBaseTab.tsx | 18 + .../DealServicesTable/DealServicesTable.tsx | 71 + .../components/DealServiceRow.tsx | 114 ++ .../components/DealServicesTitle.tsx | 12 + .../components/DealServicesTotalLabel.tsx | 26 + .../components/ServicesActions.tsx | 58 + .../FulfillmentBaseTabBody.tsx | 34 + .../GeneralDataForm/GeneralDataForm.tsx | 115 ++ .../components/LockCheckbox/LockCheckbox.tsx | 28 + .../PaymentLinkButton/PaymentLinkButton.tsx | 68 + .../PrintDealBarcodesButton.tsx | 63 + .../ProductImageDropzone.tsx | 68 + .../ProductImageDropzone/useImageDropzone.ts | 27 + .../ProductSelect/ProductSelect.tsx | 55 + .../utils/renderProductOption.tsx | 51 + .../ProductView/ProductView.module.css | 36 + .../components/ProductView/ProductView.tsx | 156 ++ .../components/ProductFieldsList.tsx | 37 + .../components/ProductServicesTable.tsx | 146 ++ .../components/ProductViewActions.tsx | 64 + .../hooks/useProductServicesTableColumns.tsx | 70 + .../ProductsActions/ProductsActions.tsx | 60 + .../ServiceSelect/ServiceSelect.tsx | 51 + .../contexts/FulfillmentBaseContext.tsx | 68 + .../hooks/cruds/useDealProductCrud.tsx | 153 ++ .../hooks/cruds/useDealServiceCrud.tsx | 153 ++ .../hooks/cruds/useProductServiceCrud.tsx | 102 + .../hooks/cruds/useProductsCrud.tsx | 49 + .../hooks/cruds/useServicesCrud.tsx | 49 + .../hooks/lists/useDealProductsList.ts | 49 + .../hooks/lists/useDealServicesList.ts | 49 + .../hooks/lists/useProductsList.ts | 42 + .../hooks/lists/useServicesKitsList.ts | 33 + .../hooks/lists/useServicesList.ts | 34 + .../utils/useProductAndServiceTabState.tsx | 148 ++ .../DealProductEditorModal.tsx | 87 + .../DealServiceEditorModal.tsx | 114 ++ .../components/ServiceWithPriceInput.tsx | 115 ++ .../DuplicateServicesModal.tsx | 93 + .../ProductEditorModal/ProductEditorModal.tsx | 122 ++ .../ProductServiceEditorModal.tsx | 100 + .../ServicesKitSelectModal.tsx | 57 + .../components/ServicesKitSelect.tsx | 23 + .../FulfillmentBaseTab/types/service.ts | 4 + src/modules/modules.tsx | 28 + src/modules/modulesFileGen/modulesFileGen.ts | 86 + .../templates/modulesFileTemplate.hbs | 34 + src/modules/types.tsx | 18 + src/modules/utils/isModuleInProject.ts | 8 + src/utils/baseFormInputProps.ts | 7 + yarn.lock | 49 +- 92 files changed, 8404 insertions(+), 103 deletions(-) rename src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/{ => components}/Footer.tsx (100%) rename src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/{ => components}/Footer.tsx (100%) create mode 100644 src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx create mode 100644 src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx create mode 100644 src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx create mode 100644 src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts create mode 100644 src/components/selects/ObjectMultiSelect/ObjectMultiSelect.tsx create mode 100644 src/components/ui/ImageDropzone/ImageDropzone.tsx create mode 100644 src/components/ui/ImageDropzone/types.ts create mode 100644 src/hooks/cruds/baseCrud/getCommonQueryClient.ts create mode 100644 src/modals/base/BaseFormModal/BaseFormModal.tsx create mode 100644 src/modals/base/BaseFormModal/BaseFormModalActions.tsx create mode 100644 src/modules/connectModules.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.module.css create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServiceRow.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTitle.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTotalLabel.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/ServicesActions.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/GeneralDataForm/GeneralDataForm.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PaymentLinkButton/PaymentLinkButton.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PrintDealBarcodesButton/PrintDealBarcodesButton.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/ProductImageDropzone.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/useImageDropzone.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/ProductSelect.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/utils/renderProductOption.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.module.css create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductFieldsList.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductServicesTable.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductViewActions.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductsActions/ProductsActions.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ServiceSelect/ServiceSelect.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/cruds/useDealProductCrud.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/cruds/useDealServiceCrud.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/cruds/useProductServiceCrud.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/cruds/useProductsCrud.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/cruds/useServicesCrud.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useDealProductsList.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useDealServicesList.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useProductsList.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useServicesKitsList.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useServicesList.ts create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/utils/useProductAndServiceTabState.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DealProductEditorModal/DealProductEditorModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DealServiceEditorModal/DealServiceEditorModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DealServiceEditorModal/components/ServiceWithPriceInput.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DuplicateServicesModal/DuplicateServicesModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductEditorModal/ProductEditorModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ServicesKitSelectModal/ServicesKitSelectModal.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ServicesKitSelectModal/components/ServicesKitSelect.tsx create mode 100644 src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/types/service.ts create mode 100644 src/modules/modules.tsx create mode 100644 src/modules/modulesFileGen/modulesFileGen.ts create mode 100644 src/modules/modulesFileGen/templates/modulesFileTemplate.hbs create mode 100644 src/modules/types.tsx create mode 100644 src/modules/utils/isModuleInProject.ts create mode 100644 src/utils/baseFormInputProps.ts diff --git a/package.json b/package.json index 20cae99..2caa562 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build": "next build", "start": "next start", "lint": "next lint", - "generate-client": "openapi-ts && prettier --write ./src/lib/client/**/*.ts && git add ./src/lib/client" + "generate-client": "openapi-ts && prettier --write ./src/lib/client/**/*.ts && git add ./src/lib/client", + "generate-modules": "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" }, "dependencies": { "@dnd-kit/core": "^6.3.1", @@ -15,6 +16,7 @@ "@dnd-kit/sortable": "^10.0.0", "@mantine/core": "8.1.2", "@mantine/dates": "^8.2.7", + "@mantine/dropzone": "^8.3.1", "@mantine/form": "^8.1.3", "@mantine/hooks": "8.1.2", "@mantine/modals": "^8.2.1", @@ -31,6 +33,7 @@ "date-fns-tz": "^3.2.0", "dayjs": "^1.11.15", "framer-motion": "^12.23.7", + "handlebars": "^4.7.8", "i18n-iso-countries": "^7.14.0", "lexorank": "^1.0.5", "libphonenumber-js": "^1.12.10", diff --git a/src/app/deals/components/desktop/DealsTable/DealsTable.tsx b/src/app/deals/components/desktop/DealsTable/DealsTable.tsx index 49c1318..24fcbee 100644 --- a/src/app/deals/components/desktop/DealsTable/DealsTable.tsx +++ b/src/app/deals/components/desktop/DealsTable/DealsTable.tsx @@ -3,11 +3,13 @@ import { IconMoodSad } from "@tabler/icons-react"; import { Group, Pagination, Stack, Text } from "@mantine/core"; import useDealsTableColumns from "@/app/deals/components/desktop/DealsTable/useDealsTableColumns"; import { useDealsContext } from "@/app/deals/contexts/DealsContext"; +import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext"; import BaseTable from "@/components/ui/BaseTable/BaseTable"; import { useDrawersContext } from "@/drawers/DrawersContext"; import { DealSchema } from "@/lib/client"; const DealsTable: FC = () => { + const { selectedProject } = useProjectsContext(); const { deals, paginationInfo, page, setPage, sortingForm, dealsCrud } = useDealsContext(); const { openDrawer } = useDrawersContext(); @@ -20,6 +22,7 @@ const DealsTable: FC = () => { value: deal, onChange: deal => dealsCrud.onUpdate(deal.id, deal), onDelete: dealsCrud.onDelete, + project: selectedProject, }, }); }, diff --git a/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx b/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx index de496a0..55b1d96 100644 --- a/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx +++ b/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx @@ -35,7 +35,7 @@ const TopToolPanel: FC = ({ view, setView }) => { title: "Создание проекта", withCloseButton: true, innerProps: { - onChange: values => projectsCrud.onCreate(values.name), + onChange: projectsCrud.onCreate, }, }); }; diff --git a/src/app/deals/components/shared/CreateBoardButton/CreateBoardButton.tsx b/src/app/deals/components/shared/CreateBoardButton/CreateBoardButton.tsx index c3b8aed..246f590 100644 --- a/src/app/deals/components/shared/CreateBoardButton/CreateBoardButton.tsx +++ b/src/app/deals/components/shared/CreateBoardButton/CreateBoardButton.tsx @@ -11,7 +11,7 @@ const CreateBoardButton = () => { boardsCrud.onCreate({ name })} getChildren={startEditing => ( { const { dealsCrud } = useDealsContext(); const onSubmit = (values: CreateDealForm) => { - dealsCrud.onCreate(values.name); + dealsCrud.onCreate(values); setIsCreating(prevState => !prevState); setIsTransitionEnded(false); }; diff --git a/src/app/deals/components/shared/CreateStatusButton/CreateStatusButton.tsx b/src/app/deals/components/shared/CreateStatusButton/CreateStatusButton.tsx index da09f23..33cf9ce 100644 --- a/src/app/deals/components/shared/CreateStatusButton/CreateStatusButton.tsx +++ b/src/app/deals/components/shared/CreateStatusButton/CreateStatusButton.tsx @@ -17,7 +17,7 @@ const CreateStatusButton = () => { className={styles["inner-container"]}> statusesCrud.onCreate({ name })} getChildren={startEditing => (
{ + const { selectedProject } = useProjectsContext(); const { dealsCrud } = useDealsContext(); const { openDrawer } = useDrawersContext(); @@ -19,6 +21,7 @@ const DealCard = ({ deal }: Props) => { value: deal, onChange: deal => dealsCrud.onUpdate(deal.id, deal), onDelete: dealsCrud.onDelete, + project: selectedProject, }, }); }; diff --git a/src/app/deals/drawers/BoardsMobileEditorDrawer/components/CreateBoardButton.tsx b/src/app/deals/drawers/BoardsMobileEditorDrawer/components/CreateBoardButton.tsx index f30099b..72a1505 100644 --- a/src/app/deals/drawers/BoardsMobileEditorDrawer/components/CreateBoardButton.tsx +++ b/src/app/deals/drawers/BoardsMobileEditorDrawer/components/CreateBoardButton.tsx @@ -2,9 +2,10 @@ import { FC } from "react"; import { IconPlus } from "@tabler/icons-react"; import { Box, Group, Text } from "@mantine/core"; import { modals } from "@mantine/modals"; +import { CreateBoardSchema } from "@/lib/client"; type Props = { - onCreateBoard: (name: string) => void; + onCreateBoard: (data: Partial) => void; }; const CreateBoardButton: FC = ({ onCreateBoard }) => { @@ -14,7 +15,7 @@ const CreateBoardButton: FC = ({ onCreateBoard }) => { title: "Создание доски", withCloseButton: true, innerProps: { - onChange: values => onCreateBoard(values.name), + onChange: values => onCreateBoard(values), }, }); }; diff --git a/src/app/deals/drawers/DealEditorDrawer/DealEditorDrawer.tsx b/src/app/deals/drawers/DealEditorDrawer/DealEditorDrawer.tsx index 4cde60f..b498356 100644 --- a/src/app/deals/drawers/DealEditorDrawer/DealEditorDrawer.tsx +++ b/src/app/deals/drawers/DealEditorDrawer/DealEditorDrawer.tsx @@ -6,12 +6,13 @@ import DealEditorBody from "@/app/deals/drawers/DealEditorDrawer/components/Deal import Header from "@/app/deals/drawers/DealEditorDrawer/components/Header"; import { DrawerProps } from "@/drawers/types"; import useIsMobile from "@/hooks/utils/useIsMobile"; -import { DealSchema } from "@/lib/client"; +import { DealSchema, ProjectSchema } from "@/lib/client"; type Props = { value: DealSchema; onChange: (deal: DealSchema) => void; onDelete: (deal: DealSchema, onSuccess: () => void) => void; + project: ProjectSchema | null; }; const DealEditorDrawer: FC> = ({ @@ -24,7 +25,7 @@ const DealEditorDrawer: FC> = ({ return ( > = ({ props.onChange(deal); }} onDelete={value => props.onDelete(value, onClose)} + project={props.project} /> ); diff --git a/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx b/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx index 985cc11..49c19b2 100644 --- a/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx +++ b/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx @@ -1,17 +1,55 @@ -import React, { FC } from "react"; -import { IconCircleDotted, IconEdit } from "@tabler/icons-react"; -import { Tabs, Text } from "@mantine/core"; +import React, { FC, ReactNode } from "react"; +import { IconEdit } from "@tabler/icons-react"; +import { motion } from "framer-motion"; +import { Box, Tabs } from "@mantine/core"; import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab"; -import { DealSchema } from "@/lib/client"; +import { DealSchema, ProjectSchema } from "@/lib/client"; +import { MODULES } from "@/modules/modules"; import styles from "../DealEditorDrawer.module.css"; type Props = { value: DealSchema; onChange: (deal: DealSchema) => void; onDelete: (deal: DealSchema) => void; + project: ProjectSchema | null; }; const DealEditorBody: FC = props => { + const getTabPanel = (value: string, component: ReactNode): ReactNode => ( + + + + {component} + + + + ); + + const getModuleTabs = () => + props.project?.builtInModules.map(module => { + const moduleRender = MODULES[module.key].renderInfo; + return ( + + {moduleRender.label} + + ); + }); + + const getModuleTabPanels = () => + props.project?.builtInModules.map(module => + getTabPanel(module.key, MODULES[module.key]?.getTab?.(props)) + ); + return ( = props => { leftSection={}> Общая информация - }> - Mock - + {getModuleTabs()} - - - - - mock - + {getTabPanel("general", )} + {getModuleTabPanels()} ); }; diff --git a/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab.tsx b/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab.tsx index 5776412..f522026 100644 --- a/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab.tsx +++ b/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab.tsx @@ -1,7 +1,7 @@ import React, { FC } from "react"; import { Stack, Text, TextInput } from "@mantine/core"; import { useForm } from "@mantine/form"; -import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/Footer"; +import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/components/Footer"; import BoardSelect from "@/components/selects/BoardSelect/BoardSelect"; import StatusSelect from "@/components/selects/StatusSelect/StatusSelect"; import { BoardSchema, DealSchema, StatusSchema } from "@/lib/client"; diff --git a/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/Footer.tsx b/src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/components/Footer.tsx similarity index 100% rename from src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/Footer.tsx rename to src/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/components/Footer.tsx diff --git a/src/app/deals/drawers/ProjectEditorDrawer/components/ProjectEditorBody.tsx b/src/app/deals/drawers/ProjectEditorDrawer/components/ProjectEditorBody.tsx index 5864e50..07c4243 100644 --- a/src/app/deals/drawers/ProjectEditorDrawer/components/ProjectEditorBody.tsx +++ b/src/app/deals/drawers/ProjectEditorDrawer/components/ProjectEditorBody.tsx @@ -1,7 +1,10 @@ import { FC } from "react"; -import { IconEdit } from "@tabler/icons-react"; +import { IconBlocks, IconEdit } from "@tabler/icons-react"; import { Tabs } from "@mantine/core"; -import GeneralTab from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab"; +import { + GeneralTab, + ModulesTab, +} from "@/app/deals/drawers/ProjectEditorDrawer/tabs"; import { ProjectSchema } from "@/lib/client"; import styles from "../ProjectEditorDrawer.module.css"; @@ -22,10 +25,18 @@ const ProjectEditorBody: FC = props => { leftSection={}> Общая информация + }> + Модули + + + + ); }; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab.tsx index 84566d3..b097dd8 100644 --- a/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab.tsx +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/GeneralTab.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; import { Stack, TextInput } from "@mantine/core"; import { useForm } from "@mantine/form"; -import Footer from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/Footer"; +import Footer from "@/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/components/Footer"; import { ProjectSchema } from "@/lib/client"; type Props = { @@ -10,7 +10,7 @@ type Props = { onDelete: (value: ProjectSchema) => void; }; -const GeneralTab: FC = ({ value, onChange, onDelete }) => { +export const GeneralTab: FC = ({ value, onChange, onDelete }) => { const form = useForm({ initialValues: value, validate: { @@ -38,5 +38,3 @@ const GeneralTab: FC = ({ value, onChange, onDelete }) => { ); }; - -export default GeneralTab; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/Footer.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/components/Footer.tsx similarity index 100% rename from src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/Footer.tsx rename to src/app/deals/drawers/ProjectEditorDrawer/tabs/GeneralTab/components/Footer.tsx diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx new file mode 100644 index 0000000..e9dbe8a --- /dev/null +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx @@ -0,0 +1,41 @@ +import { FC } from "react"; +import { isEqual } from "lodash"; +import { Button, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { ProjectSchema } from "@/lib/client"; +import ModulesTable from "./components/ModulesTable"; + +type Props = { + value: ProjectSchema; + onChange: (value: ProjectSchema) => void; +}; + +export const ModulesTab: FC = ({ value, onChange }) => { + const form = useForm({ + initialValues: value, + }); + + const onSubmit = (values: ProjectSchema) => { + onChange(values); + form.setInitialValues(values); + }; + + return ( +
+ + + form.setFieldValue("builtInModules", modules) + } + /> + + +
+ ); +}; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx new file mode 100644 index 0000000..85ad395 --- /dev/null +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx @@ -0,0 +1,32 @@ +import { FC, useRef } from "react"; +import { Divider, Stack } from "@mantine/core"; +import useModulesTableColumns from "@/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns"; +import BaseTable from "@/components/ui/BaseTable/BaseTable"; +import { BuiltInModuleSchema } from "@/lib/client"; +import { MODULES } from "@/modules/modules"; + +type Props = { + selectedRecords: BuiltInModuleSchema[]; + onSelectedRecordsChange: (records: BuiltInModuleSchema[]) => void; +}; + +const ModulesTable: FC = props => { + const columns = useModulesTableColumns(); + const modules = useRef( + Object.values(MODULES).map(module => module.modelData) + ); + + return ( + + + + + ); +}; + +export default ModulesTable; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx new file mode 100644 index 0000000..7b75d03 --- /dev/null +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx @@ -0,0 +1,24 @@ +import { useMemo } from "react"; +import { DataTableColumn } from "mantine-datatable"; +import { BuiltInModuleSchema } from "@/lib/client"; + +const useModulesTableColumns = () => { + return useMemo( + () => + [ + { + accessor: "label", + title: "Название", + width: "30%", + }, + { + title: "Описание", + accessor: "description", + width: "70%", + }, + ] as DataTableColumn[], + [] + ); +}; + +export default useModulesTableColumns; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts b/src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts new file mode 100644 index 0000000..0b07abb --- /dev/null +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/index.ts @@ -0,0 +1,2 @@ +export { GeneralTab } from "./GeneralTab/GeneralTab"; +export { ModulesTab } from "./ModulesTab/ModulesTab"; diff --git a/src/app/deals/drawers/ProjectsMobileEditorDrawer/components/CreateProjectButton.tsx b/src/app/deals/drawers/ProjectsMobileEditorDrawer/components/CreateProjectButton.tsx index e88de67..a7227e9 100644 --- a/src/app/deals/drawers/ProjectsMobileEditorDrawer/components/CreateProjectButton.tsx +++ b/src/app/deals/drawers/ProjectsMobileEditorDrawer/components/CreateProjectButton.tsx @@ -13,7 +13,7 @@ const CreateProjectButton: FC = () => { title: "Создание проекта", withCloseButton: true, innerProps: { - onChange: values => projectsCrud.onCreate(values.name), + onChange: projectsCrud.onCreate, }, }); }; diff --git a/src/app/deals/drawers/StatusesMobileEditorDrawer/components/CreateStatusButton.tsx b/src/app/deals/drawers/StatusesMobileEditorDrawer/components/CreateStatusButton.tsx index 00df9fe..8464740 100644 --- a/src/app/deals/drawers/StatusesMobileEditorDrawer/components/CreateStatusButton.tsx +++ b/src/app/deals/drawers/StatusesMobileEditorDrawer/components/CreateStatusButton.tsx @@ -13,7 +13,7 @@ const CreateStatusButton: FC = () => { title: "Создание колонки", withCloseButton: true, innerProps: { - onChange: values => statusesCrud.onCreate(values.name), + onChange: statusesCrud.onCreate, }, }); }; diff --git a/src/components/selects/ObjectMultiSelect/ObjectMultiSelect.tsx b/src/components/selects/ObjectMultiSelect/ObjectMultiSelect.tsx new file mode 100644 index 0000000..41f6a6e --- /dev/null +++ b/src/components/selects/ObjectMultiSelect/ObjectMultiSelect.tsx @@ -0,0 +1,108 @@ +"use client"; + +import { useEffect, useMemo, useState } from "react"; +import { groupBy, omit } from "lodash"; +import { MultiSelect, MultiSelectProps } from "@mantine/core"; + +interface ObjectWithIdAndName { + id: number; + name: string; +} + +export type MultiselectObjectType = T; + +type ControlledValueProps = { + value: MultiselectObjectType[]; + onChange: (value: MultiselectObjectType[]) => void; +}; + +type CustomLabelAndKeyProps = { + getLabelFn: (item: MultiselectObjectType) => string; + getValueFn: (item: MultiselectObjectType) => string; +}; +type RestProps = { + defaultValue?: MultiselectObjectType[]; + onChange: (value: MultiselectObjectType[]) => void; + data: MultiselectObjectType[]; + groupBy?: (item: MultiselectObjectType) => string; + filterBy?: (item: MultiselectObjectType) => boolean; +}; +const defaultGetLabelFn = (item: T): string => { + return item.name; +}; + +const defaultGetValueFn = (item: T): string => { + return item.id.toString(); +}; +export type ObjectMultiSelectProps = (RestProps & + Partial>) & + Omit & + (T extends ObjectWithIdAndName + ? Partial> + : CustomLabelAndKeyProps); + +const ObjectMultiSelect = (props: ObjectMultiSelectProps) => { + const isControlled = "value" in props; + const haveGetValueFn = "getValueFn" in props; + const haveGetLabelFn = "getLabelFn" in props; + + const [internalValue, setInternalValue] = useState< + MultiselectObjectType[] | undefined + >(props.defaultValue); + + const value = (isControlled ? props.value : internalValue) || []; + + const getValueFn = + (haveGetValueFn && props.getValueFn) || defaultGetValueFn; + const getLabelFn = + (haveGetLabelFn && props.getLabelFn) || defaultGetLabelFn; + + const data = useMemo(() => { + const propsData = props.filterBy + ? props.data.filter(props.filterBy) + : props.data; + if (props.groupBy) { + const groupedData = groupBy(propsData, props.groupBy); + return Object.entries(groupedData).map(([group, items]) => ({ + group, + items: items.map(item => ({ + label: getLabelFn(item), + value: getValueFn(item), + })), + })); + } + return propsData.map(item => ({ + label: getLabelFn(item), + value: getValueFn(item), + })); + }, [props.data, props.groupBy]); + + const handleOnChange = (event: string[]) => { + const objects = props.data.filter(item => + event.includes(getValueFn(item)) + ); + if (isControlled) { + props.onChange(objects); + return; + } + setInternalValue(objects); + }; + + useEffect(() => { + if (isControlled || !internalValue) return; + props.onChange(internalValue); + }, [internalValue]); + + const restProps = omit(props, "getValueFn", "getLabelFn", "filterBy"); + + return ( + getValueFn(item))} + onChange={handleOnChange} + data={data} + /> + ); +}; + +export default ObjectMultiSelect; diff --git a/src/components/selects/ObjectSelect/ObjectSelect.tsx b/src/components/selects/ObjectSelect/ObjectSelect.tsx index e05bb92..7b80302 100644 --- a/src/components/selects/ObjectSelect/ObjectSelect.tsx +++ b/src/components/selects/ObjectSelect/ObjectSelect.tsx @@ -1,3 +1,5 @@ +"use client"; + import { useEffect, useMemo, useState } from "react"; import { groupBy, omit } from "lodash"; import { Select, SelectProps } from "@mantine/core"; @@ -33,6 +35,7 @@ const defaultGetValueFn = (item: T): string => { if (!item) return item; return item.id.toString(); }; + export type ObjectSelectProps = (RestProps & Partial>) & Omit & diff --git a/src/components/ui/BaseTable/BaseTable.tsx b/src/components/ui/BaseTable/BaseTable.tsx index 7a99702..b042a39 100644 --- a/src/components/ui/BaseTable/BaseTable.tsx +++ b/src/components/ui/BaseTable/BaseTable.tsx @@ -4,11 +4,10 @@ import { DataTable, DataTableProps } from "mantine-datatable"; function BaseTable(props: DataTableProps) { return ( diff --git a/src/components/ui/ImageDropzone/ImageDropzone.tsx b/src/components/ui/ImageDropzone/ImageDropzone.tsx new file mode 100644 index 0000000..010ffbc --- /dev/null +++ b/src/components/ui/ImageDropzone/ImageDropzone.tsx @@ -0,0 +1,119 @@ +import { FC } from "react"; +import { IconPhoto, IconUpload, IconX } from "@tabler/icons-react"; +import { omit } from "lodash"; +import { + Button, + Fieldset, + Flex, + Group, + Image, + Loader, + rem, + Text, +} from "@mantine/core"; +import { Dropzone, DropzoneProps, FileWithPath } from "@mantine/dropzone"; +import UseImageDropzone from "./types"; + +interface RestProps { + imageDropzone: UseImageDropzone; + onDrop: (files: FileWithPath[]) => void; +} + +type Props = Omit & RestProps; + +const ImageDropzone: FC = (props: Props) => { + const { showDropzone, setShowDropzone, isLoading, imageUrlInputProps } = + props.imageDropzone; + + const restProps = omit(props, ["imageDropzone"]); + + const getDropzone = () => ( + + + + + + + + + + + + +
+ + Перенесите изображение или нажмите чтоб выбрать файл + +
+
+
+ ); + + const getBody = () => { + if (imageUrlInputProps?.value && !showDropzone) { + return ; + } + return getDropzone(); + }; + + return ( + +
+ + {isLoading ? : getBody()} + +
+ {!showDropzone && ( + + )} +
+ ); +}; + +export default ImageDropzone; diff --git a/src/components/ui/ImageDropzone/types.ts b/src/components/ui/ImageDropzone/types.ts new file mode 100644 index 0000000..7af0a38 --- /dev/null +++ b/src/components/ui/ImageDropzone/types.ts @@ -0,0 +1,12 @@ +import { Dispatch, SetStateAction } from "react"; +import BaseFormInputProps from "@/utils/baseFormInputProps"; + +type UseImageDropzone = { + showDropzone: boolean; + setShowDropzone: Dispatch>; + isLoading: boolean; + setIsLoading: Dispatch>; + imageUrlInputProps?: BaseFormInputProps; +}; + +export default UseImageDropzone; diff --git a/src/hooks/cruds/baseCrud/getCommonQueryClient.ts b/src/hooks/cruds/baseCrud/getCommonQueryClient.ts new file mode 100644 index 0000000..6b4432d --- /dev/null +++ b/src/hooks/cruds/baseCrud/getCommonQueryClient.ts @@ -0,0 +1,38 @@ +import { useQueryClient } from "@tanstack/react-query"; +import { AxiosError } from "axios"; +import { HttpValidationError } from "@/lib/client"; +import { notifications } from "@/lib/notifications"; + +type Props = { + key: string; + queryKey: any[]; +}; + +const getCommonQueryClient = ({ key, queryKey }: Props) => { + const queryClient = useQueryClient(); + + const onError = ( + error: AxiosError, + _: any, + context: any + ) => { + console.error(error); + notifications.error({ + message: error.response?.data?.detail as string | undefined, + }); + if (context?.previous) { + queryClient.setQueryData(queryKey, context.previous); + } + }; + + const onSettled = () => { + queryClient.invalidateQueries({ + predicate: (query: { queryKey: any }) => + query.queryKey[0]?._id === key, + }); + }; + + return { queryClient, onError, onSettled }; +}; + +export default getCommonQueryClient; diff --git a/src/hooks/cruds/baseCrud/useCrudOperations.tsx b/src/hooks/cruds/baseCrud/useCrudOperations.tsx index 2efdd58..b27ca93 100644 --- a/src/hooks/cruds/baseCrud/useCrudOperations.tsx +++ b/src/hooks/cruds/baseCrud/useCrudOperations.tsx @@ -1,14 +1,10 @@ import React from "react"; -import { - useMutation, - UseMutationOptions, - useQueryClient, -} from "@tanstack/react-query"; +import { useMutation, UseMutationOptions } from "@tanstack/react-query"; import { AxiosError } from "axios"; import { Text } from "@mantine/core"; import { modals } from "@mantine/modals"; +import getCommonQueryClient from "@/hooks/cruds/baseCrud/getCommonQueryClient"; import { HttpValidationError } from "@/lib/client"; -import { notifications } from "@/lib/notifications"; import { sortByLexorank } from "@/utils/lexorank"; import { BaseEntity, @@ -17,10 +13,17 @@ import { UpdateMutationOptions, } from "./types"; -type CrudOperations = { - onCreate: (name: string) => void; - onUpdate: (id: number, update: TUpdate) => void; - onDelete: (entity: TEntity) => void; +type CrudOperations< + TEntity, + TUpdate, + TCreate, + HasGetCreateEntity extends boolean, +> = { + onCreate: HasGetCreateEntity extends true + ? (data: Partial, onSuccess?: () => void) => void + : (data: TCreate, onSuccess?: () => void) => void; + onUpdate: (id: number, update: TUpdate, onSuccess?: () => void) => void; + onDelete: (entity: TEntity, onSuccess?: () => void) => void; }; type UseEntityOperationsProps = { @@ -43,12 +46,32 @@ type UseEntityOperationsProps = { DeleteMutationOptions >; }; - getCreateEntity: (name: string) => TCreate | null; + getCreateEntity?: (data: Partial) => TCreate | null; getUpdateEntity: (oldEntity: TEntity, update: TUpdate) => TEntity; getDeleteConfirmTitle: (entity: TEntity) => string; }; -const useCrudOperations = < +function useCrudOperations< + TEntity extends BaseEntity, + TUpdate extends object, + TCreate extends object, +>( + props: UseEntityOperationsProps & { + getCreateEntity: (data: Partial) => TCreate | null; + } +): CrudOperations; + +function useCrudOperations< + TEntity extends BaseEntity, + TUpdate extends object, + TCreate extends object, +>( + props: UseEntityOperationsProps & { + getCreateEntity?: undefined; + } +): CrudOperations; + +function useCrudOperations< TEntity extends BaseEntity, TUpdate extends object, TCreate extends object, @@ -61,30 +84,14 @@ const useCrudOperations = < getDeleteConfirmTitle, }: UseEntityOperationsProps): CrudOperations< TEntity, - TUpdate -> => { - const queryClient = useQueryClient(); - - const onError = ( - error: AxiosError, - _: any, - context: any - ) => { - console.error(error); - notifications.error({ - message: error.response?.data?.detail as string | undefined, - }); - if (context?.previous) { - queryClient.setQueryData(queryKey, context.previous); - } - }; - - const onSettled = () => { - queryClient.invalidateQueries({ - predicate: (query: { queryKey: any }) => - query.queryKey[0]?._id === key, - }); - }; + TUpdate, + TCreate, + boolean +> { + const { queryClient, onError, onSettled } = getCommonQueryClient({ + queryKey, + key, + }); const createMutation = useMutation({ ...mutations.create, @@ -102,6 +109,7 @@ const useCrudOperations = < const previous = queryClient.getQueryData(queryKey); queryClient.setQueryData(queryKey, (old: { items: TEntity[] }) => { + if (!old) return; let updated = old.items.map((entity: TEntity) => entity.id === update.id ? getUpdateEntity(entity, update) @@ -145,26 +153,43 @@ const useCrudOperations = < }, }); - const onCreate = (name: string) => { - const entity = getCreateEntity(name); - if (!entity) return; - createMutation.mutate({ - body: { - entity, + const onCreate = (data: any, onSuccess?: () => void) => { + let entity: TCreate; + if (getCreateEntity) { + const result = getCreateEntity(data); + if (!result) return; + entity = result; + } else { + entity = data; + } + + createMutation.mutate( + { + body: { + entity, + }, + path: undefined, + query: undefined, }, - path: undefined, - query: undefined, - }); + { + onSuccess, + } + ); }; - const onUpdate = async (id: number, update: TUpdate) => { - updateMutation.mutate({ - body: { - entity: update, + const onUpdate = (id: number, update: TUpdate, onSuccess?: () => void) => { + updateMutation.mutate( + { + body: { + entity: update, + }, + path: { pk: id }, + query: undefined, }, - path: { pk: id }, - query: undefined, - }); + { + onSuccess, + } + ); }; const onDelete = (entity: TEntity, onSuccess?: () => void) => { @@ -175,13 +200,14 @@ const useCrudOperations = < ), confirmProps: { color: "red" }, onConfirm: () => { - deleteMutation.mutate({ path: { pk: entity.id } } as any); - onSuccess && onSuccess(); + deleteMutation.mutate({ path: { pk: entity.id } } as any, { + onSuccess, + }); }, }); }; return { onCreate, onUpdate, onDelete }; -}; +} export default useCrudOperations; diff --git a/src/hooks/cruds/useBoardsCrud.tsx b/src/hooks/cruds/useBoardsCrud.tsx index 18e1153..993df43 100644 --- a/src/hooks/cruds/useBoardsCrud.tsx +++ b/src/hooks/cruds/useBoardsCrud.tsx @@ -19,7 +19,7 @@ type UseBoardsOperationsProps = { }; export type BoardsCrud = { - onCreate: (name: string) => void; + onCreate: (data: Partial) => void; onUpdate: (boardId: number, board: UpdateBoardSchema) => void; onDelete: (board: BoardSchema) => void; }; @@ -38,14 +38,14 @@ export const useBoardsCrud = ({ update: updateBoardMutation(), delete: deleteBoardMutation(), }, - getCreateEntity: name => { + getCreateEntity: data => { if (!projectId) return null; const lastBoard = getMaxByLexorank(boards); const newLexorank = getNewLexorank( lastBoard ? LexoRank.parse(lastBoard.lexorank) : null ); return { - name, + name: data.name!, projectId, lexorank: newLexorank.toString(), }; diff --git a/src/hooks/cruds/useDealsCrud.tsx b/src/hooks/cruds/useDealsCrud.tsx index 201e4a3..4c2632a 100644 --- a/src/hooks/cruds/useDealsCrud.tsx +++ b/src/hooks/cruds/useDealsCrud.tsx @@ -21,7 +21,7 @@ type UseDealsOperationsProps = { }; export type DealsCrud = { - onCreate: (name: string) => void; + onCreate: (entity: Partial) => void; onUpdate: (dealId: number, deal: UpdateDealSchema) => void; onDelete: (deal: DealSchema, onSuccess?: () => void) => void; }; @@ -40,7 +40,7 @@ export const useDealsCrud = ({ update: updateDealMutation(), delete: deleteDealMutation(), }, - getCreateEntity: name => { + getCreateEntity: data => { if (!boardId || statuses.length === 0) return null; const firstStatus = statuses[0]; const filteredDeals = deals.filter( @@ -55,7 +55,7 @@ export const useDealsCrud = ({ firstDeal ? LexoRank.parse(firstDeal.lexorank) : null ); return { - name, + name: data.name!, boardId, statusId: firstStatus.id, lexorank: newLexorank.toString(), diff --git a/src/hooks/cruds/useProjectsCrud.tsx b/src/hooks/cruds/useProjectsCrud.tsx index 0064ec6..f3629b2 100644 --- a/src/hooks/cruds/useProjectsCrud.tsx +++ b/src/hooks/cruds/useProjectsCrud.tsx @@ -15,7 +15,7 @@ type Props = { }; export type ProjectsCrud = { - onCreate: (name: string) => void; + onCreate: (data: Partial) => void; onUpdate: (projectId: number, project: UpdateProjectSchema) => void; onDelete: (project: ProjectSchema, onSuccess?: () => void) => void; }; @@ -33,7 +33,7 @@ export const useProjectsCrud = ({ queryKey }: Props): ProjectsCrud => { update: updateProjectMutation(), delete: deleteProjectMutation(), }, - getCreateEntity: name => ({ name }), + getCreateEntity: data => ({ name: data.name! }), getUpdateEntity: (old, update) => ({ ...old, name: update.name ?? old.name, diff --git a/src/hooks/cruds/useStatusesCrud.tsx b/src/hooks/cruds/useStatusesCrud.tsx index dd111cf..7778ace 100644 --- a/src/hooks/cruds/useStatusesCrud.tsx +++ b/src/hooks/cruds/useStatusesCrud.tsx @@ -19,7 +19,7 @@ type Props = { }; export type StatusesCrud = { - onCreate: (name: string) => void; + onCreate: (entity: Partial) => void; onUpdate: (statusId: number, status: UpdateStatusSchema) => void; onDelete: (status: StatusSchema) => void; }; @@ -41,14 +41,14 @@ export const useStatusesCrud = ({ update: updateStatusMutation(), delete: deleteStatusMutation(), }, - getCreateEntity: name => { + getCreateEntity: data => { if (!boardId) return null; const lastBoard = getMaxByLexorank(statuses); const newLexorank = getNewLexorank( lastBoard ? LexoRank.parse(lastBoard.lexorank) : null ); return { - name, + name: data.name!, boardId, lexorank: newLexorank.toString(), }; diff --git a/src/lib/client/@tanstack/react-query.gen.ts b/src/lib/client/@tanstack/react-query.gen.ts index a0eee04..bd9e7e5 100644 --- a/src/lib/client/@tanstack/react-query.gen.ts +++ b/src/lib/client/@tanstack/react-query.gen.ts @@ -9,34 +9,81 @@ import { import type { AxiosError } from "axios"; import { client as _heyApiClient } from "../client.gen"; import { + addKitToDealProduct, createBoard, createDeal, + createDealProduct, + createDealProductService, + createDealService, + createProduct, createProject, + createService, + createServicesKit, createStatus, deleteBoard, deleteDeal, + deleteDealProduct, + deleteDealProductService, + deleteDealService, + deleteProduct, deleteProject, + deleteService, + deleteServicesKit, deleteStatus, + duplicateProductServices, getBoards, + getBuiltInModules, + getDealProducts, getDeals, + getDealServices, + getProducts, getProjects, + getServices, + getServicesKits, getStatuses, updateBoard, updateDeal, + updateDealProduct, + updateDealProductService, + updateDealService, + updateProduct, updateProject, + updateService, + updateServicesKit, updateStatus, type Options, } from "../sdk.gen"; import type { + AddKitToDealProductData, + AddKitToDealProductError, + AddKitToDealProductResponse, CreateBoardData, CreateBoardError, CreateBoardResponse2, CreateDealData, CreateDealError, + CreateDealProductData, + CreateDealProductError, + CreateDealProductResponse2, + CreateDealProductServiceData, + CreateDealProductServiceError, + CreateDealProductServiceResponse, CreateDealResponse2, + CreateDealServiceData, + CreateDealServiceError, + CreateDealServiceResponse2, + CreateProductData, + CreateProductError, + CreateProductResponse2, CreateProjectData, CreateProjectError, CreateProjectResponse2, + CreateServiceData, + CreateServiceError, + CreateServiceResponse2, + CreateServicesKitData, + CreateServicesKitError, + CreateServicesKitResponse2, CreateStatusData, CreateStatusError, CreateStatusResponse2, @@ -45,28 +92,75 @@ import type { DeleteBoardResponse2, DeleteDealData, DeleteDealError, + DeleteDealProductData, + DeleteDealProductError, + DeleteDealProductResponse2, + DeleteDealProductServiceData, + DeleteDealProductServiceError, + DeleteDealProductServiceResponse, DeleteDealResponse2, + DeleteDealServiceData, + DeleteDealServiceError, + DeleteDealServiceResponse2, + DeleteProductData, + DeleteProductError, + DeleteProductResponse2, DeleteProjectData, DeleteProjectError, DeleteProjectResponse2, + DeleteServiceData, + DeleteServiceError, + DeleteServiceResponse2, + DeleteServicesKitData, + DeleteServicesKitError, + DeleteServicesKitResponse2, DeleteStatusData, DeleteStatusError, DeleteStatusResponse2, + DuplicateProductServicesData, + DuplicateProductServicesError, + DuplicateProductServicesResponse, GetBoardsData, + GetBuiltInModulesData, + GetDealProductsData, GetDealsData, GetDealsError, + GetDealServicesData, GetDealsResponse2, + GetProductsData, + GetProductsError, + GetProductsResponse2, GetProjectsData, + GetServicesData, + GetServicesKitsData, GetStatusesData, UpdateBoardData, UpdateBoardError, UpdateBoardResponse2, UpdateDealData, UpdateDealError, + UpdateDealProductData, + UpdateDealProductError, + UpdateDealProductResponse2, + UpdateDealProductServiceData, + UpdateDealProductServiceError, + UpdateDealProductServiceResponse, UpdateDealResponse2, + UpdateDealServiceData, + UpdateDealServiceError, + UpdateDealServiceResponse2, + UpdateProductData, + UpdateProductError, + UpdateProductResponse2, UpdateProjectData, UpdateProjectError, UpdateProjectResponse2, + UpdateServiceData, + UpdateServiceError, + UpdateServiceResponse2, + UpdateServicesKitData, + UpdateServicesKitError, + UpdateServicesKitResponse2, UpdateStatusData, UpdateStatusError, UpdateStatusResponse2, @@ -439,6 +533,30 @@ export const updateDealMutation = ( return mutationOptions; }; +export const getBuiltInModulesQueryKey = ( + options?: Options +) => createQueryKey("getBuiltInModules", options); + +/** + * Get Built In Modules + */ +export const getBuiltInModulesOptions = ( + options?: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getBuiltInModules({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getBuiltInModulesQueryKey(options), + }); +}; + export const getProjectsQueryKey = (options?: Options) => createQueryKey("getProjects", options); @@ -684,3 +802,895 @@ export const updateStatusMutation = ( }; return mutationOptions; }; + +export const getDealProductsQueryKey = ( + options: Options +) => createQueryKey("getDealProducts", options); + +/** + * Get Deal Products + */ +export const getDealProductsOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getDealProducts({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getDealProductsQueryKey(options), + }); +}; + +export const createDealProductQueryKey = ( + options: Options +) => createQueryKey("createDealProduct", options); + +/** + * Create Deal Product + */ +export const createDealProductOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createDealProduct({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createDealProductQueryKey(options), + }); +}; + +/** + * Create Deal Product + */ +export const createDealProductMutation = ( + options?: Partial> +): UseMutationOptions< + CreateDealProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateDealProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createDealProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Deal Product + */ +export const deleteDealProductMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteDealProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteDealProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteDealProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Deal Product + */ +export const updateDealProductMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateDealProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateDealProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateDealProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const addKitToDealProductQueryKey = ( + options: Options +) => createQueryKey("addKitToDealProduct", options); + +/** + * Add Kit To Deal Product + */ +export const addKitToDealProductOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await addKitToDealProduct({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: addKitToDealProductQueryKey(options), + }); +}; + +/** + * Add Kit To Deal Product + */ +export const addKitToDealProductMutation = ( + options?: Partial> +): UseMutationOptions< + AddKitToDealProductResponse, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + AddKitToDealProductResponse, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await addKitToDealProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const createDealProductServiceQueryKey = ( + options: Options +) => createQueryKey("createDealProductService", options); + +/** + * Create Deal Product Service + */ +export const createDealProductServiceOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createDealProductService({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createDealProductServiceQueryKey(options), + }); +}; + +/** + * Create Deal Product Service + */ +export const createDealProductServiceMutation = ( + options?: Partial> +): UseMutationOptions< + CreateDealProductServiceResponse, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateDealProductServiceResponse, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createDealProductService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Deal Product Service + */ +export const deleteDealProductServiceMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteDealProductServiceResponse, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteDealProductServiceResponse, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteDealProductService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Deal Product Service + */ +export const updateDealProductServiceMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateDealProductServiceResponse, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateDealProductServiceResponse, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateDealProductService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const duplicateProductServicesQueryKey = ( + options: Options +) => createQueryKey("duplicateProductServices", options); + +/** + * Copy Product Services + */ +export const duplicateProductServicesOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await duplicateProductServices({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: duplicateProductServicesQueryKey(options), + }); +}; + +/** + * Copy Product Services + */ +export const duplicateProductServicesMutation = ( + options?: Partial> +): UseMutationOptions< + DuplicateProductServicesResponse, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DuplicateProductServicesResponse, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await duplicateProductServices({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const getDealServicesQueryKey = ( + options: Options +) => createQueryKey("getDealServices", options); + +/** + * Get Deal Services + */ +export const getDealServicesOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getDealServices({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getDealServicesQueryKey(options), + }); +}; + +export const createDealServiceQueryKey = ( + options: Options +) => createQueryKey("createDealService", options); + +/** + * Create Deal Service + */ +export const createDealServiceOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createDealService({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createDealServiceQueryKey(options), + }); +}; + +/** + * Create Deal Service + */ +export const createDealServiceMutation = ( + options?: Partial> +): UseMutationOptions< + CreateDealServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateDealServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createDealService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Deal Service + */ +export const deleteDealServiceMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteDealServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteDealServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteDealService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Deal Service + */ +export const updateDealServiceMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateDealServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateDealServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateDealService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const getProductsQueryKey = (options?: Options) => + createQueryKey("getProducts", options); + +/** + * Get Products + */ +export const getProductsOptions = (options?: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getProducts({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getProductsQueryKey(options), + }); +}; + +export const getProductsInfiniteQueryKey = ( + options?: Options +): QueryKey> => + createQueryKey("getProducts", options, true); + +/** + * Get Products + */ +export const getProductsInfiniteOptions = ( + options?: Options +) => { + return infiniteQueryOptions< + GetProductsResponse2, + AxiosError, + InfiniteData, + QueryKey>, + | number + | null + | Pick< + QueryKey>[0], + "body" | "headers" | "path" | "query" + > + >( + // @ts-ignore + { + queryFn: async ({ pageParam, queryKey, signal }) => { + // @ts-ignore + const page: Pick< + QueryKey>[0], + "body" | "headers" | "path" | "query" + > = + typeof pageParam === "object" + ? pageParam + : { + query: { + page: pageParam, + }, + }; + const params = createInfiniteParams(queryKey, page); + const { data } = await getProducts({ + ...options, + ...params, + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getProductsInfiniteQueryKey(options), + } + ); +}; + +export const createProductQueryKey = (options: Options) => + createQueryKey("createProduct", options); + +/** + * Create Product + */ +export const createProductOptions = (options: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createProduct({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createProductQueryKey(options), + }); +}; + +/** + * Create Product + */ +export const createProductMutation = ( + options?: Partial> +): UseMutationOptions< + CreateProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Product + */ +export const deleteProductMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Product + */ +export const updateProductMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateProductResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateProductResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateProduct({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const getServicesQueryKey = (options?: Options) => + createQueryKey("getServices", options); + +/** + * Get Services + */ +export const getServicesOptions = (options?: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getServices({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getServicesQueryKey(options), + }); +}; + +export const createServiceQueryKey = (options: Options) => + createQueryKey("createService", options); + +/** + * Create Service + */ +export const createServiceOptions = (options: Options) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createService({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createServiceQueryKey(options), + }); +}; + +/** + * Create Service + */ +export const createServiceMutation = ( + options?: Partial> +): UseMutationOptions< + CreateServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Service + */ +export const deleteServiceMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Service + */ +export const updateServiceMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateServiceResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateServiceResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateService({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +export const getServicesKitsQueryKey = ( + options?: Options +) => createQueryKey("getServicesKits", options); + +/** + * Get Services Kits + */ +export const getServicesKitsOptions = ( + options?: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getServicesKits({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: getServicesKitsQueryKey(options), + }); +}; + +export const createServicesKitQueryKey = ( + options: Options +) => createQueryKey("createServicesKit", options); + +/** + * Create Services Kit + */ +export const createServicesKitOptions = ( + options: Options +) => { + return queryOptions({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await createServicesKit({ + ...options, + ...queryKey[0], + signal, + throwOnError: true, + }); + return data; + }, + queryKey: createServicesKitQueryKey(options), + }); +}; + +/** + * Create Services Kit + */ +export const createServicesKitMutation = ( + options?: Partial> +): UseMutationOptions< + CreateServicesKitResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + CreateServicesKitResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await createServicesKit({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Delete Services Kit + */ +export const deleteServicesKitMutation = ( + options?: Partial> +): UseMutationOptions< + DeleteServicesKitResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + DeleteServicesKitResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await deleteServicesKit({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; + +/** + * Update Services Kit + */ +export const updateServicesKitMutation = ( + options?: Partial> +): UseMutationOptions< + UpdateServicesKitResponse2, + AxiosError, + Options +> => { + const mutationOptions: UseMutationOptions< + UpdateServicesKitResponse2, + AxiosError, + Options + > = { + mutationFn: async localOptions => { + const { data } = await updateServicesKit({ + ...options, + ...localOptions, + throwOnError: true, + }); + return data; + }, + }; + return mutationOptions; +}; diff --git a/src/lib/client/sdk.gen.ts b/src/lib/client/sdk.gen.ts index 52a2516..4113260 100644 --- a/src/lib/client/sdk.gen.ts +++ b/src/lib/client/sdk.gen.ts @@ -3,15 +3,36 @@ import type { Client, Options as ClientOptions, TDataShape } from "./client"; import { client as _heyApiClient } from "./client.gen"; import type { + AddKitToDealProductData, + AddKitToDealProductErrors, + AddKitToDealProductResponses, CreateBoardData, CreateBoardErrors, CreateBoardResponses, CreateDealData, CreateDealErrors, + CreateDealProductData, + CreateDealProductErrors, + CreateDealProductResponses, + CreateDealProductServiceData, + CreateDealProductServiceErrors, + CreateDealProductServiceResponses, CreateDealResponses, + CreateDealServiceData, + CreateDealServiceErrors, + CreateDealServiceResponses, + CreateProductData, + CreateProductErrors, + CreateProductResponses, CreateProjectData, CreateProjectErrors, CreateProjectResponses, + CreateServiceData, + CreateServiceErrors, + CreateServiceResponses, + CreateServicesKitData, + CreateServicesKitErrors, + CreateServicesKitResponses, CreateStatusData, CreateStatusErrors, CreateStatusResponses, @@ -20,21 +41,57 @@ import type { DeleteBoardResponses, DeleteDealData, DeleteDealErrors, + DeleteDealProductData, + DeleteDealProductErrors, + DeleteDealProductResponses, + DeleteDealProductServiceData, + DeleteDealProductServiceErrors, + DeleteDealProductServiceResponses, DeleteDealResponses, + DeleteDealServiceData, + DeleteDealServiceErrors, + DeleteDealServiceResponses, + DeleteProductData, + DeleteProductErrors, + DeleteProductResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, + DeleteServiceData, + DeleteServiceErrors, + DeleteServiceResponses, + DeleteServicesKitData, + DeleteServicesKitErrors, + DeleteServicesKitResponses, DeleteStatusData, DeleteStatusErrors, DeleteStatusResponses, + DuplicateProductServicesData, + DuplicateProductServicesErrors, + DuplicateProductServicesResponses, GetBoardsData, GetBoardsErrors, GetBoardsResponses, + GetBuiltInModulesData, + GetBuiltInModulesResponses, + GetDealProductsData, + GetDealProductsErrors, + GetDealProductsResponses, GetDealsData, GetDealsErrors, + GetDealServicesData, + GetDealServicesErrors, + GetDealServicesResponses, GetDealsResponses, + GetProductsData, + GetProductsErrors, + GetProductsResponses, GetProjectsData, GetProjectsResponses, + GetServicesData, + GetServicesKitsData, + GetServicesKitsResponses, + GetServicesResponses, GetStatusesData, GetStatusesErrors, GetStatusesResponses, @@ -43,45 +100,115 @@ import type { UpdateBoardResponses, UpdateDealData, UpdateDealErrors, + UpdateDealProductData, + UpdateDealProductErrors, + UpdateDealProductResponses, + UpdateDealProductServiceData, + UpdateDealProductServiceErrors, + UpdateDealProductServiceResponses, UpdateDealResponses, + UpdateDealServiceData, + UpdateDealServiceErrors, + UpdateDealServiceResponses, + UpdateProductData, + UpdateProductErrors, + UpdateProductResponses, UpdateProjectData, UpdateProjectErrors, UpdateProjectResponses, + UpdateServiceData, + UpdateServiceErrors, + UpdateServiceResponses, + UpdateServicesKitData, + UpdateServicesKitErrors, + UpdateServicesKitResponses, UpdateStatusData, UpdateStatusErrors, UpdateStatusResponses, } from "./types.gen"; import { + zAddKitToDealProductData, + zAddKitToDealProductResponse, zCreateBoardData, zCreateBoardResponse2, zCreateDealData, + zCreateDealProductData, + zCreateDealProductResponse2, + zCreateDealProductServiceData, + zCreateDealProductServiceResponse, zCreateDealResponse2, + zCreateDealServiceData, + zCreateDealServiceResponse2, + zCreateProductData, + zCreateProductResponse2, zCreateProjectData, zCreateProjectResponse2, + zCreateServiceData, + zCreateServiceResponse2, + zCreateServicesKitData, + zCreateServicesKitResponse2, zCreateStatusData, zCreateStatusResponse2, zDeleteBoardData, zDeleteBoardResponse2, zDeleteDealData, + zDeleteDealProductData, + zDeleteDealProductResponse2, + zDeleteDealProductServiceData, + zDeleteDealProductServiceResponse, zDeleteDealResponse2, + zDeleteDealServiceData, + zDeleteDealServiceResponse2, + zDeleteProductData, + zDeleteProductResponse2, zDeleteProjectData, zDeleteProjectResponse2, + zDeleteServiceData, + zDeleteServiceResponse2, + zDeleteServicesKitData, + zDeleteServicesKitResponse2, zDeleteStatusData, zDeleteStatusResponse2, + zDuplicateProductServicesData, + zDuplicateProductServicesResponse, zGetBoardsData, zGetBoardsResponse2, + zGetBuiltInModulesData, + zGetBuiltInModulesResponse, + zGetDealProductsData, + zGetDealProductsResponse2, zGetDealsData, + zGetDealServicesData, + zGetDealServicesResponse2, zGetDealsResponse2, + zGetProductsData, + zGetProductsResponse2, zGetProjectsData, zGetProjectsResponse2, + zGetServicesData, + zGetServicesKitsData, + zGetServicesKitsResponse, + zGetServicesResponse2, zGetStatusesData, zGetStatusesResponse2, zUpdateBoardData, zUpdateBoardResponse2, zUpdateDealData, + zUpdateDealProductData, + zUpdateDealProductResponse2, + zUpdateDealProductServiceData, + zUpdateDealProductServiceResponse, zUpdateDealResponse2, + zUpdateDealServiceData, + zUpdateDealServiceResponse2, + zUpdateProductData, + zUpdateProductResponse2, zUpdateProjectData, zUpdateProjectResponse2, + zUpdateServiceData, + zUpdateServiceResponse2, + zUpdateServicesKitData, + zUpdateServicesKitResponse2, zUpdateStatusData, zUpdateStatusResponse2, } from "./zod.gen"; @@ -303,6 +430,29 @@ export const updateDeal = ( }); }; +/** + * Get Built In Modules + */ +export const getBuiltInModules = ( + options?: Options +) => { + return (options?.client ?? _heyApiClient).get< + GetBuiltInModulesResponses, + unknown, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetBuiltInModulesData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetBuiltInModulesResponse.parseAsync(data); + }, + url: "/module/built-in/", + ...options, + }); +}; + /** * Get Projects */ @@ -502,3 +652,634 @@ export const updateStatus = ( }, }); }; + +/** + * Get Deal Products + */ +export const getDealProducts = ( + options: Options +) => { + return (options.client ?? _heyApiClient).get< + GetDealProductsResponses, + GetDealProductsErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetDealProductsData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetDealProductsResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/{dealId}", + ...options, + }); +}; + +/** + * Create Deal Product + */ +export const createDealProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateDealProductResponses, + CreateDealProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateDealProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateDealProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Deal Product + */ +export const deleteDealProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteDealProductResponses, + DeleteDealProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteDealProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteDealProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}", + ...options, + }); +}; + +/** + * Update Deal Product + */ +export const updateDealProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateDealProductResponses, + UpdateDealProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateDealProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateDealProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Add Kit To Deal Product + */ +export const addKitToDealProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + AddKitToDealProductResponses, + AddKitToDealProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zAddKitToDealProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zAddKitToDealProductResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/add-services-kit", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Create Deal Product Service + */ +export const createDealProductService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateDealProductServiceResponses, + CreateDealProductServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateDealProductServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateDealProductServiceResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/service", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Deal Product Service + */ +export const deleteDealProductService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteDealProductServiceResponses, + DeleteDealProductServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteDealProductServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteDealProductServiceResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}/service/{serviceId}", + ...options, + }); +}; + +/** + * Update Deal Product Service + */ +export const updateDealProductService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateDealProductServiceResponses, + UpdateDealProductServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateDealProductServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateDealProductServiceResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}/service/{serviceId}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Copy Product Services + */ +export const duplicateProductServices = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + DuplicateProductServicesResponses, + DuplicateProductServicesErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDuplicateProductServicesData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDuplicateProductServicesResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-product/services/duplicate", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Get Deal Services + */ +export const getDealServices = ( + options: Options +) => { + return (options.client ?? _heyApiClient).get< + GetDealServicesResponses, + GetDealServicesErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetDealServicesData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetDealServicesResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-service/{dealId}", + ...options, + }); +}; + +/** + * Create Deal Service + */ +export const createDealService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateDealServiceResponses, + CreateDealServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateDealServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateDealServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-service/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Deal Service + */ +export const deleteDealService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteDealServiceResponses, + DeleteDealServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteDealServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteDealServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-service/{dealId}/service/{serviceId}", + ...options, + }); +}; + +/** + * Update Deal Service + */ +export const updateDealService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateDealServiceResponses, + UpdateDealServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateDealServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateDealServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/deal-service/{dealId}/service/{serviceId}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Get Products + */ +export const getProducts = ( + options?: Options +) => { + return (options?.client ?? _heyApiClient).get< + GetProductsResponses, + GetProductsErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetProductsData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetProductsResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/product/", + ...options, + }); +}; + +/** + * Create Product + */ +export const createProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateProductResponses, + CreateProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/product/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Product + */ +export const deleteProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteProductResponses, + DeleteProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/product/{pk}", + ...options, + }); +}; + +/** + * Update Product + */ +export const updateProduct = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateProductResponses, + UpdateProductErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateProductData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateProductResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/product/{pk}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Get Services + */ +export const getServices = ( + options?: Options +) => { + return (options?.client ?? _heyApiClient).get< + GetServicesResponses, + unknown, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetServicesData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetServicesResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/service/", + ...options, + }); +}; + +/** + * Create Service + */ +export const createService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateServiceResponses, + CreateServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/service/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Service + */ +export const deleteService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteServiceResponses, + DeleteServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/service/{pk}", + ...options, + }); +}; + +/** + * Update Service + */ +export const updateService = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateServiceResponses, + UpdateServiceErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateServiceData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateServiceResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/service/{pk}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Get Services Kits + */ +export const getServicesKits = ( + options?: Options +) => { + return (options?.client ?? _heyApiClient).get< + GetServicesKitsResponses, + unknown, + ThrowOnError + >({ + requestValidator: async data => { + return await zGetServicesKitsData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zGetServicesKitsResponse.parseAsync(data); + }, + url: "/modules/fulfillment-base/services-kit/", + ...options, + }); +}; + +/** + * Create Services Kit + */ +export const createServicesKit = ( + options: Options +) => { + return (options.client ?? _heyApiClient).post< + CreateServicesKitResponses, + CreateServicesKitErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zCreateServicesKitData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zCreateServicesKitResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/services-kit/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; + +/** + * Delete Services Kit + */ +export const deleteServicesKit = ( + options: Options +) => { + return (options.client ?? _heyApiClient).delete< + DeleteServicesKitResponses, + DeleteServicesKitErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zDeleteServicesKitData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zDeleteServicesKitResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/services-kit/{pk}", + ...options, + }); +}; + +/** + * Update Services Kit + */ +export const updateServicesKit = ( + options: Options +) => { + return (options.client ?? _heyApiClient).patch< + UpdateServicesKitResponses, + UpdateServicesKitErrors, + ThrowOnError + >({ + requestValidator: async data => { + return await zUpdateServicesKitData.parseAsync(data); + }, + responseType: "json", + responseValidator: async data => { + return await zUpdateServicesKitResponse2.parseAsync(data); + }, + url: "/modules/fulfillment-base/services-kit/{pk}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }); +}; diff --git a/src/lib/client/types.gen.ts b/src/lib/client/types.gen.ts index 68634b4..fbfffc1 100644 --- a/src/lib/client/types.gen.ts +++ b/src/lib/client/types.gen.ts @@ -22,6 +22,32 @@ export type BoardSchema = { projectId: number; }; +/** + * BuiltInModuleSchema + */ +export type BuiltInModuleSchema = { + /** + * Id + */ + id: number; + /** + * Key + */ + key: string; + /** + * Label + */ + label: string; + /** + * Iconname + */ + iconName: string; + /** + * Description + */ + description: string; +}; + /** * CreateBoardRequest */ @@ -58,6 +84,46 @@ export type CreateBoardSchema = { lexorank: string; }; +/** + * CreateDealProductRequest + */ +export type CreateDealProductRequest = { + entity: CreateDealProductSchema; +}; + +/** + * CreateDealProductResponse + */ +export type CreateDealProductResponse = { + /** + * Message + */ + message: string; + entity: DealProductSchema; +}; + +/** + * CreateDealProductSchema + */ +export type CreateDealProductSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Quantity + */ + quantity: number; + /** + * Comment + */ + comment: string; +}; + /** * CreateDealRequest */ @@ -98,6 +164,142 @@ export type CreateDealSchema = { statusId: number; }; +/** + * CreateDealServiceRequest + */ +export type CreateDealServiceRequest = { + entity: CreateDealServiceSchema; +}; + +/** + * CreateDealServiceResponse + */ +export type CreateDealServiceResponse = { + /** + * Message + */ + message: string; + entity: DealServiceSchema; +}; + +/** + * CreateDealServiceSchema + */ +export type CreateDealServiceSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Serviceid + */ + serviceId: number; + /** + * Quantity + */ + quantity: number; + /** + * Price + */ + price: number; +}; + +/** + * CreateProductRequest + */ +export type CreateProductRequest = { + entity: CreateProductSchema; +}; + +/** + * CreateProductResponse + */ +export type CreateProductResponse = { + /** + * Message + */ + message: string; + entity: ProductSchema; +}; + +/** + * CreateProductSchema + */ +export type CreateProductSchema = { + /** + * Name + */ + name: string; + /** + * Article + */ + article: string; + /** + * Factoryarticle + */ + factoryArticle: string; + /** + * Brand + */ + brand: string | null; + /** + * Color + */ + color: string | null; + /** + * Composition + */ + composition: string | null; + /** + * Size + */ + size: string | null; + /** + * Additionalinfo + */ + additionalInfo: string | null; +}; + +/** + * CreateProductServiceRequest + */ +export type CreateProductServiceRequest = { + entity: CreateProductServiceSchema; +}; + +/** + * CreateProductServiceResponse + */ +export type CreateProductServiceResponse = { + /** + * Message + */ + message: string; + entity: ProductServiceSchema; +}; + +/** + * CreateProductServiceSchema + */ +export type CreateProductServiceSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Serviceid + */ + serviceId: number; + /** + * Price + */ + price: number; +}; + /** * CreateProjectRequest */ @@ -126,6 +328,95 @@ export type CreateProjectSchema = { name: string; }; +/** + * CreateServiceRequest + */ +export type CreateServiceRequest = { + entity: CreateServiceSchema; +}; + +/** + * CreateServiceResponse + */ +export type CreateServiceResponse = { + /** + * Message + */ + message: string; + entity: ServiceSchema; +}; + +/** + * CreateServiceSchema + */ +export type CreateServiceSchema = { + /** + * Id + */ + id: number; + /** + * Name + */ + name: string; + category: ServiceCategorySchema; + /** + * Price + */ + price: number; + /** + * Servicetype + */ + serviceType: number; + /** + * Priceranges + */ + priceRanges: Array; + /** + * Cost + */ + cost: number | null; + /** + * Lexorank + */ + lexorank: string; +}; + +/** + * CreateServicesKitRequest + */ +export type CreateServicesKitRequest = { + entity: CreateServicesKitSchema; +}; + +/** + * CreateServicesKitResponse + */ +export type CreateServicesKitResponse = { + /** + * Message + */ + message: string; + entity: ServicesKitSchema; +}; + +/** + * CreateServicesKitSchema + */ +export type CreateServicesKitSchema = { + /** + * Name + */ + name: string; + /** + * Servicetype + */ + serviceType: number; + /** + * Servicesids + */ + servicesIds: Array; +}; + /** * CreateStatusRequest */ @@ -162,6 +453,61 @@ export type CreateStatusSchema = { lexorank: string; }; +/** + * DealProductAddKitRequest + */ +export type DealProductAddKitRequest = { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Kitid + */ + kitId: number; +}; + +/** + * DealProductAddKitResponse + */ +export type DealProductAddKitResponse = { + /** + * Message + */ + message: string; +}; + +/** + * DealProductSchema + */ +export type DealProductSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + product: ProductSchema; + /** + * Quantity + */ + quantity: number; + /** + * Comment + */ + comment: string; + /** + * Productservices + */ + productServices: Array; +}; + /** * DealSchema */ @@ -186,6 +532,33 @@ export type DealSchema = { createdAt: string; }; +/** + * DealServiceSchema + */ +export type DealServiceSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Serviceid + */ + serviceId: number; + service: ServiceSchema; + /** + * Quantity + */ + quantity: number; + /** + * Price + */ + price: number; + /** + * Isfixedprice + */ + isFixedPrice: boolean; +}; + /** * DeleteBoardResponse */ @@ -196,6 +569,16 @@ export type DeleteBoardResponse = { message: string; }; +/** + * DeleteDealProductResponse + */ +export type DeleteDealProductResponse = { + /** + * Message + */ + message: string; +}; + /** * DeleteDealResponse */ @@ -206,6 +589,36 @@ export type DeleteDealResponse = { message: string; }; +/** + * DeleteDealServiceResponse + */ +export type DeleteDealServiceResponse = { + /** + * Message + */ + message: string; +}; + +/** + * DeleteProductResponse + */ +export type DeleteProductResponse = { + /** + * Message + */ + message: string; +}; + +/** + * DeleteProductServiceResponse + */ +export type DeleteProductServiceResponse = { + /** + * Message + */ + message: string; +}; + /** * DeleteProjectResponse */ @@ -216,6 +629,26 @@ export type DeleteProjectResponse = { message: string; }; +/** + * DeleteServiceResponse + */ +export type DeleteServiceResponse = { + /** + * Message + */ + message: string; +}; + +/** + * DeleteServicesKitResponse + */ +export type DeleteServicesKitResponse = { + /** + * Message + */ + message: string; +}; + /** * DeleteStatusResponse */ @@ -226,6 +659,16 @@ export type DeleteStatusResponse = { message: string; }; +/** + * GetAllBuiltInModulesResponse + */ +export type GetAllBuiltInModulesResponse = { + /** + * Items + */ + items: Array; +}; + /** * GetBoardsResponse */ @@ -236,6 +679,26 @@ export type GetBoardsResponse = { items: Array; }; +/** + * GetDealProductsResponse + */ +export type GetDealProductsResponse = { + /** + * Items + */ + items: Array; +}; + +/** + * GetDealServicesResponse + */ +export type GetDealServicesResponse = { + /** + * Items + */ + items: Array; +}; + /** * GetDealsResponse */ @@ -247,6 +710,16 @@ export type GetDealsResponse = { paginationInfo: PaginationInfoSchema; }; +/** + * GetProductsResponse + */ +export type GetProductsResponse = { + /** + * Items + */ + items: Array; +}; + /** * GetProjectsResponse */ @@ -257,6 +730,26 @@ export type GetProjectsResponse = { items: Array; }; +/** + * GetServicesKitResponse + */ +export type GetServicesKitResponse = { + /** + * Items + */ + items: Array; +}; + +/** + * GetServicesResponse + */ +export type GetServicesResponse = { + /** + * Items + */ + items: Array; +}; + /** * GetStatusesResponse */ @@ -291,6 +784,121 @@ export type PaginationInfoSchema = { totalItems: number; }; +/** + * ProductImageSchema + */ +export type ProductImageSchema = { + /** + * Id + */ + id: number; + /** + * Productid + */ + productId: number; + /** + * Imageurl + */ + imageUrl: string; +}; + +/** + * ProductSchema + */ +export type ProductSchema = { + /** + * Name + */ + name: string; + /** + * Article + */ + article: string; + /** + * Factoryarticle + */ + factoryArticle: string; + /** + * Brand + */ + brand: string | null; + /** + * Color + */ + color: string | null; + /** + * Composition + */ + composition: string | null; + /** + * Size + */ + size: string | null; + /** + * Additionalinfo + */ + additionalInfo: string | null; + /** + * Id + */ + id: number; +}; + +/** + * ProductServiceSchema + */ +export type ProductServiceSchema = { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Serviceid + */ + serviceId: number; + service: ServiceSchema; + /** + * Price + */ + price: number; + /** + * Isfixedprice + */ + isFixedPrice: boolean; +}; + +/** + * ProductServicesDuplicateRequest + */ +export type ProductServicesDuplicateRequest = { + /** + * Dealid + */ + dealId: number; + /** + * Sourcedealproductid + */ + sourceDealProductId: number; + /** + * Targetdealproductids + */ + targetDealProductIds: Array; +}; + +/** + * ProductServicesDuplicateResponse + */ +export type ProductServicesDuplicateResponse = { + /** + * Message + */ + message: string; +}; + /** * ProjectSchema */ @@ -303,6 +911,111 @@ export type ProjectSchema = { * Name */ name: string; + /** + * Builtinmodules + */ + builtInModules: Array; +}; + +/** + * ServiceCategorySchema + */ +export type ServiceCategorySchema = { + /** + * Id + */ + id: number; + /** + * Name + */ + name: string; + /** + * Dealservicerank + */ + dealServiceRank: string; + /** + * Productservicerank + */ + productServiceRank: string; +}; + +/** + * ServicePriceRangeSchema + */ +export type ServicePriceRangeSchema = { + /** + * Id + */ + id: number | null; + /** + * Fromquantity + */ + fromQuantity: number; + /** + * Toquantity + */ + toQuantity: number; + /** + * Price + */ + price: number; +}; + +/** + * ServiceSchema + */ +export type ServiceSchema = { + /** + * Id + */ + id: number; + /** + * Name + */ + name: string; + category: ServiceCategorySchema; + /** + * Price + */ + price: number; + /** + * Servicetype + */ + serviceType: number; + /** + * Priceranges + */ + priceRanges: Array; + /** + * Cost + */ + cost: number | null; + /** + * Lexorank + */ + lexorank: string; +}; + +/** + * ServicesKitSchema + */ +export type ServicesKitSchema = { + /** + * Name + */ + name: string; + /** + * Servicetype + */ + serviceType: number; + /** + * Id + */ + id: number; + /** + * Services + */ + services: Array; }; export type SortDir = "asc" | "desc"; @@ -356,6 +1069,37 @@ export type UpdateBoardSchema = { lexorank?: string | null; }; +/** + * UpdateDealProductRequest + */ +export type UpdateDealProductRequest = { + entity: UpdateDealProductSchema; +}; + +/** + * UpdateDealProductResponse + */ +export type UpdateDealProductResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateDealProductSchema + */ +export type UpdateDealProductSchema = { + /** + * Quantity + */ + quantity: number; + /** + * Comment + */ + comment: string; +}; + /** * UpdateDealRequest */ @@ -395,6 +1139,131 @@ export type UpdateDealSchema = { statusId?: number | null; }; +/** + * UpdateDealServiceRequest + */ +export type UpdateDealServiceRequest = { + entity: UpdateDealServiceSchema; +}; + +/** + * UpdateDealServiceResponse + */ +export type UpdateDealServiceResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateDealServiceSchema + */ +export type UpdateDealServiceSchema = { + /** + * Quantity + */ + quantity: number; + /** + * Price + */ + price: number; + /** + * Isfixedprice + */ + isFixedPrice: boolean; +}; + +/** + * UpdateProductRequest + */ +export type UpdateProductRequest = { + entity: UpdateProductSchema; +}; + +/** + * UpdateProductResponse + */ +export type UpdateProductResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateProductSchema + */ +export type UpdateProductSchema = { + /** + * Name + */ + name?: string | null; + /** + * Article + */ + article?: string | null; + /** + * Factoryarticle + */ + factoryArticle?: string | null; + /** + * Brand + */ + brand?: string | null; + /** + * Color + */ + color?: string | null; + /** + * Composition + */ + composition?: string | null; + /** + * Size + */ + size?: string | null; + /** + * Additionalinfo + */ + additionalInfo?: string | null; + /** + * Images + */ + images?: Array | null; +}; + +/** + * UpdateProductServiceRequest + */ +export type UpdateProductServiceRequest = { + entity: UpdateProductServiceSchema; +}; + +/** + * UpdateProductServiceResponse + */ +export type UpdateProductServiceResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateProductServiceSchema + */ +export type UpdateProductServiceSchema = { + /** + * Price + */ + price: number; + /** + * Isfixedprice + */ + isFixedPrice: boolean; +}; + /** * UpdateProjectRequest */ @@ -420,6 +1289,97 @@ export type UpdateProjectSchema = { * Name */ name?: string | null; + /** + * Builtinmodules + */ + builtInModules?: Array; +}; + +/** + * UpdateServiceRequest + */ +export type UpdateServiceRequest = { + entity: UpdateServiceSchema; +}; + +/** + * UpdateServiceResponse + */ +export type UpdateServiceResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateServiceSchema + */ +export type UpdateServiceSchema = { + /** + * Id + */ + id: number; + /** + * Name + */ + name: string; + category: ServiceCategorySchema; + /** + * Price + */ + price: number; + /** + * Servicetype + */ + serviceType: number; + /** + * Priceranges + */ + priceRanges: Array; + /** + * Cost + */ + cost: number | null; + /** + * Lexorank + */ + lexorank: string; +}; + +/** + * UpdateServicesKitRequest + */ +export type UpdateServicesKitRequest = { + entity: UpdateServicesKitSchema; +}; + +/** + * UpdateServicesKitResponse + */ +export type UpdateServicesKitResponse = { + /** + * Message + */ + message: string; +}; + +/** + * UpdateServicesKitSchema + */ +export type UpdateServicesKitSchema = { + /** + * Name + */ + name: string; + /** + * Servicetype + */ + serviceType: number; + /** + * Servicesids + */ + servicesIds: Array; }; /** @@ -739,6 +1699,23 @@ export type UpdateDealResponses = { export type UpdateDealResponse2 = UpdateDealResponses[keyof UpdateDealResponses]; +export type GetBuiltInModulesData = { + body?: never; + path?: never; + query?: never; + url: "/module/built-in/"; +}; + +export type GetBuiltInModulesResponses = { + /** + * Successful Response + */ + 200: GetAllBuiltInModulesResponse; +}; + +export type GetBuiltInModulesResponse = + GetBuiltInModulesResponses[keyof GetBuiltInModulesResponses]; + export type GetProjectsData = { body?: never; path?: never; @@ -963,6 +1940,769 @@ export type UpdateStatusResponses = { export type UpdateStatusResponse2 = UpdateStatusResponses[keyof UpdateStatusResponses]; +export type GetDealProductsData = { + body?: never; + path: { + /** + * Dealid + */ + dealId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-product/{dealId}"; +}; + +export type GetDealProductsErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type GetDealProductsError = + GetDealProductsErrors[keyof GetDealProductsErrors]; + +export type GetDealProductsResponses = { + /** + * Successful Response + */ + 200: GetDealProductsResponse; +}; + +export type GetDealProductsResponse2 = + GetDealProductsResponses[keyof GetDealProductsResponses]; + +export type CreateDealProductData = { + body: CreateDealProductRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/deal-product/"; +}; + +export type CreateDealProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateDealProductError = + CreateDealProductErrors[keyof CreateDealProductErrors]; + +export type CreateDealProductResponses = { + /** + * Successful Response + */ + 200: CreateDealProductResponse; +}; + +export type CreateDealProductResponse2 = + CreateDealProductResponses[keyof CreateDealProductResponses]; + +export type DeleteDealProductData = { + body?: never; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}"; +}; + +export type DeleteDealProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteDealProductError = + DeleteDealProductErrors[keyof DeleteDealProductErrors]; + +export type DeleteDealProductResponses = { + /** + * Successful Response + */ + 200: DeleteDealProductResponse; +}; + +export type DeleteDealProductResponse2 = + DeleteDealProductResponses[keyof DeleteDealProductResponses]; + +export type UpdateDealProductData = { + body: UpdateDealProductRequest; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}"; +}; + +export type UpdateDealProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateDealProductError = + UpdateDealProductErrors[keyof UpdateDealProductErrors]; + +export type UpdateDealProductResponses = { + /** + * Successful Response + */ + 200: UpdateDealProductResponse; +}; + +export type UpdateDealProductResponse2 = + UpdateDealProductResponses[keyof UpdateDealProductResponses]; + +export type AddKitToDealProductData = { + body: DealProductAddKitRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/deal-product/add-services-kit"; +}; + +export type AddKitToDealProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type AddKitToDealProductError = + AddKitToDealProductErrors[keyof AddKitToDealProductErrors]; + +export type AddKitToDealProductResponses = { + /** + * Successful Response + */ + 200: DealProductAddKitResponse; +}; + +export type AddKitToDealProductResponse = + AddKitToDealProductResponses[keyof AddKitToDealProductResponses]; + +export type CreateDealProductServiceData = { + body: CreateProductServiceRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/deal-product/service"; +}; + +export type CreateDealProductServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateDealProductServiceError = + CreateDealProductServiceErrors[keyof CreateDealProductServiceErrors]; + +export type CreateDealProductServiceResponses = { + /** + * Successful Response + */ + 200: CreateProductServiceResponse; +}; + +export type CreateDealProductServiceResponse = + CreateDealProductServiceResponses[keyof CreateDealProductServiceResponses]; + +export type DeleteDealProductServiceData = { + body?: never; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Serviceid + */ + serviceId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}/service/{serviceId}"; +}; + +export type DeleteDealProductServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteDealProductServiceError = + DeleteDealProductServiceErrors[keyof DeleteDealProductServiceErrors]; + +export type DeleteDealProductServiceResponses = { + /** + * Successful Response + */ + 200: DeleteProductServiceResponse; +}; + +export type DeleteDealProductServiceResponse = + DeleteDealProductServiceResponses[keyof DeleteDealProductServiceResponses]; + +export type UpdateDealProductServiceData = { + body: UpdateProductServiceRequest; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Productid + */ + productId: number; + /** + * Serviceid + */ + serviceId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-product/{dealId}/product/{productId}/service/{serviceId}"; +}; + +export type UpdateDealProductServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateDealProductServiceError = + UpdateDealProductServiceErrors[keyof UpdateDealProductServiceErrors]; + +export type UpdateDealProductServiceResponses = { + /** + * Successful Response + */ + 200: UpdateProductServiceResponse; +}; + +export type UpdateDealProductServiceResponse = + UpdateDealProductServiceResponses[keyof UpdateDealProductServiceResponses]; + +export type DuplicateProductServicesData = { + body: ProductServicesDuplicateRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/deal-product/services/duplicate"; +}; + +export type DuplicateProductServicesErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DuplicateProductServicesError = + DuplicateProductServicesErrors[keyof DuplicateProductServicesErrors]; + +export type DuplicateProductServicesResponses = { + /** + * Successful Response + */ + 200: ProductServicesDuplicateResponse; +}; + +export type DuplicateProductServicesResponse = + DuplicateProductServicesResponses[keyof DuplicateProductServicesResponses]; + +export type GetDealServicesData = { + body?: never; + path: { + /** + * Dealid + */ + dealId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-service/{dealId}"; +}; + +export type GetDealServicesErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type GetDealServicesError = + GetDealServicesErrors[keyof GetDealServicesErrors]; + +export type GetDealServicesResponses = { + /** + * Successful Response + */ + 200: GetDealServicesResponse; +}; + +export type GetDealServicesResponse2 = + GetDealServicesResponses[keyof GetDealServicesResponses]; + +export type CreateDealServiceData = { + body: CreateDealServiceRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/deal-service/"; +}; + +export type CreateDealServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateDealServiceError = + CreateDealServiceErrors[keyof CreateDealServiceErrors]; + +export type CreateDealServiceResponses = { + /** + * Successful Response + */ + 200: CreateDealServiceResponse; +}; + +export type CreateDealServiceResponse2 = + CreateDealServiceResponses[keyof CreateDealServiceResponses]; + +export type DeleteDealServiceData = { + body?: never; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Serviceid + */ + serviceId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-service/{dealId}/service/{serviceId}"; +}; + +export type DeleteDealServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteDealServiceError = + DeleteDealServiceErrors[keyof DeleteDealServiceErrors]; + +export type DeleteDealServiceResponses = { + /** + * Successful Response + */ + 200: DeleteDealServiceResponse; +}; + +export type DeleteDealServiceResponse2 = + DeleteDealServiceResponses[keyof DeleteDealServiceResponses]; + +export type UpdateDealServiceData = { + body: UpdateDealServiceRequest; + path: { + /** + * Dealid + */ + dealId: number; + /** + * Serviceid + */ + serviceId: number; + }; + query?: never; + url: "/modules/fulfillment-base/deal-service/{dealId}/service/{serviceId}"; +}; + +export type UpdateDealServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateDealServiceError = + UpdateDealServiceErrors[keyof UpdateDealServiceErrors]; + +export type UpdateDealServiceResponses = { + /** + * Successful Response + */ + 200: UpdateDealServiceResponse; +}; + +export type UpdateDealServiceResponse2 = + UpdateDealServiceResponses[keyof UpdateDealServiceResponses]; + +export type GetProductsData = { + body?: never; + path?: never; + query?: { + /** + * Searchinput + */ + searchInput?: string | null; + /** + * Page + */ + page?: number | null; + /** + * Itemsperpage + */ + itemsPerPage?: number | null; + }; + url: "/modules/fulfillment-base/product/"; +}; + +export type GetProductsErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type GetProductsError = GetProductsErrors[keyof GetProductsErrors]; + +export type GetProductsResponses = { + /** + * Successful Response + */ + 200: GetProductsResponse; +}; + +export type GetProductsResponse2 = + GetProductsResponses[keyof GetProductsResponses]; + +export type CreateProductData = { + body: CreateProductRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/product/"; +}; + +export type CreateProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateProductError = CreateProductErrors[keyof CreateProductErrors]; + +export type CreateProductResponses = { + /** + * Successful Response + */ + 200: CreateProductResponse; +}; + +export type CreateProductResponse2 = + CreateProductResponses[keyof CreateProductResponses]; + +export type DeleteProductData = { + body?: never; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/product/{pk}"; +}; + +export type DeleteProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteProductError = DeleteProductErrors[keyof DeleteProductErrors]; + +export type DeleteProductResponses = { + /** + * Successful Response + */ + 200: DeleteProductResponse; +}; + +export type DeleteProductResponse2 = + DeleteProductResponses[keyof DeleteProductResponses]; + +export type UpdateProductData = { + body: UpdateProductRequest; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/product/{pk}"; +}; + +export type UpdateProductErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateProductError = UpdateProductErrors[keyof UpdateProductErrors]; + +export type UpdateProductResponses = { + /** + * Successful Response + */ + 200: UpdateProductResponse; +}; + +export type UpdateProductResponse2 = + UpdateProductResponses[keyof UpdateProductResponses]; + +export type GetServicesData = { + body?: never; + path?: never; + query?: never; + url: "/modules/fulfillment-base/service/"; +}; + +export type GetServicesResponses = { + /** + * Successful Response + */ + 200: GetServicesResponse; +}; + +export type GetServicesResponse2 = + GetServicesResponses[keyof GetServicesResponses]; + +export type CreateServiceData = { + body: CreateServiceRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/service/"; +}; + +export type CreateServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateServiceError = CreateServiceErrors[keyof CreateServiceErrors]; + +export type CreateServiceResponses = { + /** + * Successful Response + */ + 200: CreateServiceResponse; +}; + +export type CreateServiceResponse2 = + CreateServiceResponses[keyof CreateServiceResponses]; + +export type DeleteServiceData = { + body?: never; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/service/{pk}"; +}; + +export type DeleteServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteServiceError = DeleteServiceErrors[keyof DeleteServiceErrors]; + +export type DeleteServiceResponses = { + /** + * Successful Response + */ + 200: DeleteServiceResponse; +}; + +export type DeleteServiceResponse2 = + DeleteServiceResponses[keyof DeleteServiceResponses]; + +export type UpdateServiceData = { + body: UpdateServiceRequest; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/service/{pk}"; +}; + +export type UpdateServiceErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateServiceError = UpdateServiceErrors[keyof UpdateServiceErrors]; + +export type UpdateServiceResponses = { + /** + * Successful Response + */ + 200: UpdateServiceResponse; +}; + +export type UpdateServiceResponse2 = + UpdateServiceResponses[keyof UpdateServiceResponses]; + +export type GetServicesKitsData = { + body?: never; + path?: never; + query?: never; + url: "/modules/fulfillment-base/services-kit/"; +}; + +export type GetServicesKitsResponses = { + /** + * Successful Response + */ + 200: GetServicesKitResponse; +}; + +export type GetServicesKitsResponse = + GetServicesKitsResponses[keyof GetServicesKitsResponses]; + +export type CreateServicesKitData = { + body: CreateServicesKitRequest; + path?: never; + query?: never; + url: "/modules/fulfillment-base/services-kit/"; +}; + +export type CreateServicesKitErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateServicesKitError = + CreateServicesKitErrors[keyof CreateServicesKitErrors]; + +export type CreateServicesKitResponses = { + /** + * Successful Response + */ + 200: CreateServicesKitResponse; +}; + +export type CreateServicesKitResponse2 = + CreateServicesKitResponses[keyof CreateServicesKitResponses]; + +export type DeleteServicesKitData = { + body?: never; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/services-kit/{pk}"; +}; + +export type DeleteServicesKitErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteServicesKitError = + DeleteServicesKitErrors[keyof DeleteServicesKitErrors]; + +export type DeleteServicesKitResponses = { + /** + * Successful Response + */ + 200: DeleteServicesKitResponse; +}; + +export type DeleteServicesKitResponse2 = + DeleteServicesKitResponses[keyof DeleteServicesKitResponses]; + +export type UpdateServicesKitData = { + body: UpdateServicesKitRequest; + path: { + /** + * Pk + */ + pk: number; + }; + query?: never; + url: "/modules/fulfillment-base/services-kit/{pk}"; +}; + +export type UpdateServicesKitErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UpdateServicesKitError = + UpdateServicesKitErrors[keyof UpdateServicesKitErrors]; + +export type UpdateServicesKitResponses = { + /** + * Successful Response + */ + 200: UpdateServicesKitResponse; +}; + +export type UpdateServicesKitResponse2 = + UpdateServicesKitResponses[keyof UpdateServicesKitResponses]; + export type ClientOptions = { baseURL: `${string}://${string}/api` | (string & {}); }; diff --git a/src/lib/client/zod.gen.ts b/src/lib/client/zod.gen.ts index 1015126..b36237e 100644 --- a/src/lib/client/zod.gen.ts +++ b/src/lib/client/zod.gen.ts @@ -12,6 +12,17 @@ export const zBoardSchema = z.object({ projectId: z.int(), }); +/** + * BuiltInModuleSchema + */ +export const zBuiltInModuleSchema = z.object({ + id: z.int(), + key: z.string(), + label: z.string(), + iconName: z.string(), + description: z.string(), +}); + /** * CreateBoardSchema */ @@ -36,6 +47,104 @@ export const zCreateBoardResponse = z.object({ entity: zBoardSchema, }); +/** + * CreateDealProductSchema + */ +export const zCreateDealProductSchema = z.object({ + dealId: z.int(), + productId: z.int(), + quantity: z.int(), + comment: z.string(), +}); + +/** + * CreateDealProductRequest + */ +export const zCreateDealProductRequest = z.object({ + entity: zCreateDealProductSchema, +}); + +/** + * ProductSchema + */ +export const zProductSchema = z.object({ + name: z.string(), + article: z.string(), + factoryArticle: z.string(), + brand: z.union([z.string(), z.null()]), + color: z.union([z.string(), z.null()]), + composition: z.union([z.string(), z.null()]), + size: z.union([z.string(), z.null()]), + additionalInfo: z.union([z.string(), z.null()]), + id: z.int(), +}); + +/** + * ServiceCategorySchema + */ +export const zServiceCategorySchema = z.object({ + id: z.int(), + name: z.string(), + dealServiceRank: z.string(), + productServiceRank: z.string(), +}); + +/** + * ServicePriceRangeSchema + */ +export const zServicePriceRangeSchema = z.object({ + id: z.union([z.int(), z.null()]), + fromQuantity: z.int(), + toQuantity: z.int(), + price: z.number(), +}); + +/** + * ServiceSchema + */ +export const zServiceSchema = z.object({ + id: z.int(), + name: z.string(), + category: zServiceCategorySchema, + price: z.number(), + serviceType: z.int(), + priceRanges: z.array(zServicePriceRangeSchema), + cost: z.union([z.number(), z.null()]), + lexorank: z.string(), +}); + +/** + * ProductServiceSchema + */ +export const zProductServiceSchema = z.object({ + dealId: z.int(), + productId: z.int(), + serviceId: z.int(), + service: zServiceSchema, + price: z.number(), + isFixedPrice: z.boolean(), +}); + +/** + * DealProductSchema + */ +export const zDealProductSchema = z.object({ + dealId: z.int(), + productId: z.int(), + product: zProductSchema, + quantity: z.int(), + comment: z.string(), + productServices: z.array(zProductServiceSchema), +}); + +/** + * CreateDealProductResponse + */ +export const zCreateDealProductResponse = z.object({ + message: z.string(), + entity: zDealProductSchema, +}); + /** * CreateDealSchema */ @@ -84,6 +193,97 @@ export const zCreateDealResponse = z.object({ entity: zDealSchema, }); +/** + * CreateDealServiceSchema + */ +export const zCreateDealServiceSchema = z.object({ + dealId: z.int(), + serviceId: z.int(), + quantity: z.int(), + price: z.number(), +}); + +/** + * CreateDealServiceRequest + */ +export const zCreateDealServiceRequest = z.object({ + entity: zCreateDealServiceSchema, +}); + +/** + * DealServiceSchema + */ +export const zDealServiceSchema = z.object({ + dealId: z.int(), + serviceId: z.int(), + service: zServiceSchema, + quantity: z.int(), + price: z.number(), + isFixedPrice: z.boolean(), +}); + +/** + * CreateDealServiceResponse + */ +export const zCreateDealServiceResponse = z.object({ + message: z.string(), + entity: zDealServiceSchema, +}); + +/** + * CreateProductSchema + */ +export const zCreateProductSchema = z.object({ + name: z.string(), + article: z.string(), + factoryArticle: z.string(), + brand: z.union([z.string(), z.null()]), + color: z.union([z.string(), z.null()]), + composition: z.union([z.string(), z.null()]), + size: z.union([z.string(), z.null()]), + additionalInfo: z.union([z.string(), z.null()]), +}); + +/** + * CreateProductRequest + */ +export const zCreateProductRequest = z.object({ + entity: zCreateProductSchema, +}); + +/** + * CreateProductResponse + */ +export const zCreateProductResponse = z.object({ + message: z.string(), + entity: zProductSchema, +}); + +/** + * CreateProductServiceSchema + */ +export const zCreateProductServiceSchema = z.object({ + dealId: z.int(), + productId: z.int(), + serviceId: z.int(), + price: z.number(), +}); + +/** + * CreateProductServiceRequest + */ +export const zCreateProductServiceRequest = z.object({ + entity: zCreateProductServiceSchema, +}); + +/** + * CreateProductServiceResponse + */ +export const zCreateProductServiceResponse = z.object({ + message: z.string(), + entity: zProductServiceSchema, +}); + /** * CreateProjectSchema */ @@ -104,6 +304,7 @@ export const zCreateProjectRequest = z.object({ export const zProjectSchema = z.object({ id: z.int(), name: z.string(), + builtInModules: z.array(zBuiltInModuleSchema), }); /** @@ -114,6 +315,69 @@ export const zCreateProjectResponse = z.object({ entity: zProjectSchema, }); +/** + * CreateServiceSchema + */ +export const zCreateServiceSchema = z.object({ + id: z.int(), + name: z.string(), + category: zServiceCategorySchema, + price: z.number(), + serviceType: z.int(), + priceRanges: z.array(zServicePriceRangeSchema), + cost: z.union([z.number(), z.null()]), + lexorank: z.string(), +}); + +/** + * CreateServiceRequest + */ +export const zCreateServiceRequest = z.object({ + entity: zCreateServiceSchema, +}); + +/** + * CreateServiceResponse + */ +export const zCreateServiceResponse = z.object({ + message: z.string(), + entity: zServiceSchema, +}); + +/** + * CreateServicesKitSchema + */ +export const zCreateServicesKitSchema = z.object({ + name: z.string(), + serviceType: z.int(), + servicesIds: z.array(z.int()), +}); + +/** + * CreateServicesKitRequest + */ +export const zCreateServicesKitRequest = z.object({ + entity: zCreateServicesKitSchema, +}); + +/** + * ServicesKitSchema + */ +export const zServicesKitSchema = z.object({ + name: z.string(), + serviceType: z.int(), + id: z.int(), + services: z.array(zServiceSchema), +}); + +/** + * CreateServicesKitResponse + */ +export const zCreateServicesKitResponse = z.object({ + message: z.string(), + entity: zServicesKitSchema, +}); + /** * CreateStatusSchema */ @@ -138,6 +402,22 @@ export const zCreateStatusResponse = z.object({ entity: zStatusSchema, }); +/** + * DealProductAddKitRequest + */ +export const zDealProductAddKitRequest = z.object({ + dealId: z.int(), + productId: z.int(), + kitId: z.int(), +}); + +/** + * DealProductAddKitResponse + */ +export const zDealProductAddKitResponse = z.object({ + message: z.string(), +}); + /** * DeleteBoardResponse */ @@ -145,6 +425,13 @@ export const zDeleteBoardResponse = z.object({ message: z.string(), }); +/** + * DeleteDealProductResponse + */ +export const zDeleteDealProductResponse = z.object({ + message: z.string(), +}); + /** * DeleteDealResponse */ @@ -152,6 +439,27 @@ export const zDeleteDealResponse = z.object({ message: z.string(), }); +/** + * DeleteDealServiceResponse + */ +export const zDeleteDealServiceResponse = z.object({ + message: z.string(), +}); + +/** + * DeleteProductResponse + */ +export const zDeleteProductResponse = z.object({ + message: z.string(), +}); + +/** + * DeleteProductServiceResponse + */ +export const zDeleteProductServiceResponse = z.object({ + message: z.string(), +}); + /** * DeleteProjectResponse */ @@ -159,6 +467,20 @@ export const zDeleteProjectResponse = z.object({ message: z.string(), }); +/** + * DeleteServiceResponse + */ +export const zDeleteServiceResponse = z.object({ + message: z.string(), +}); + +/** + * DeleteServicesKitResponse + */ +export const zDeleteServicesKitResponse = z.object({ + message: z.string(), +}); + /** * DeleteStatusResponse */ @@ -166,6 +488,13 @@ export const zDeleteStatusResponse = z.object({ message: z.string(), }); +/** + * GetAllBuiltInModulesResponse + */ +export const zGetAllBuiltInModulesResponse = z.object({ + items: z.array(zBuiltInModuleSchema), +}); + /** * GetBoardsResponse */ @@ -173,6 +502,20 @@ export const zGetBoardsResponse = z.object({ items: z.array(zBoardSchema), }); +/** + * GetDealProductsResponse + */ +export const zGetDealProductsResponse = z.object({ + items: z.array(zDealProductSchema), +}); + +/** + * GetDealServicesResponse + */ +export const zGetDealServicesResponse = z.object({ + items: z.array(zDealServiceSchema), +}); + /** * PaginationInfoSchema */ @@ -189,6 +532,13 @@ export const zGetDealsResponse = z.object({ paginationInfo: zPaginationInfoSchema, }); +/** + * GetProductsResponse + */ +export const zGetProductsResponse = z.object({ + items: z.array(zProductSchema), +}); + /** * GetProjectsResponse */ @@ -196,6 +546,20 @@ export const zGetProjectsResponse = z.object({ items: z.array(zProjectSchema), }); +/** + * GetServicesKitResponse + */ +export const zGetServicesKitResponse = z.object({ + items: z.array(zServicesKitSchema), +}); + +/** + * GetServicesResponse + */ +export const zGetServicesResponse = z.object({ + items: z.array(zServiceSchema), +}); + /** * GetStatusesResponse */ @@ -219,6 +583,31 @@ export const zHttpValidationError = z.object({ detail: z.optional(z.array(zValidationError)), }); +/** + * ProductImageSchema + */ +export const zProductImageSchema = z.object({ + id: z.int(), + productId: z.int(), + imageUrl: z.string(), +}); + +/** + * ProductServicesDuplicateRequest + */ +export const zProductServicesDuplicateRequest = z.object({ + dealId: z.int(), + sourceDealProductId: z.int(), + targetDealProductIds: z.array(z.int()), +}); + +/** + * ProductServicesDuplicateResponse + */ +export const zProductServicesDuplicateResponse = z.object({ + message: z.string(), +}); + export const zSortDir = z.enum(["asc", "desc"]); /** @@ -243,6 +632,28 @@ export const zUpdateBoardResponse = z.object({ message: z.string(), }); +/** + * UpdateDealProductSchema + */ +export const zUpdateDealProductSchema = z.object({ + quantity: z.int(), + comment: z.string(), +}); + +/** + * UpdateDealProductRequest + */ +export const zUpdateDealProductRequest = z.object({ + entity: zUpdateDealProductSchema, +}); + +/** + * UpdateDealProductResponse + */ +export const zUpdateDealProductResponse = z.object({ + message: z.string(), +}); + /** * UpdateDealSchema */ @@ -267,11 +678,86 @@ export const zUpdateDealResponse = z.object({ message: z.string(), }); +/** + * UpdateDealServiceSchema + */ +export const zUpdateDealServiceSchema = z.object({ + quantity: z.int(), + price: z.number(), + isFixedPrice: z.boolean(), +}); + +/** + * UpdateDealServiceRequest + */ +export const zUpdateDealServiceRequest = z.object({ + entity: zUpdateDealServiceSchema, +}); + +/** + * UpdateDealServiceResponse + */ +export const zUpdateDealServiceResponse = z.object({ + message: z.string(), +}); + +/** + * UpdateProductSchema + */ +export const zUpdateProductSchema = z.object({ + name: z.optional(z.union([z.string(), z.null()])), + article: z.optional(z.union([z.string(), z.null()])), + factoryArticle: z.optional(z.union([z.string(), z.null()])), + brand: z.optional(z.union([z.string(), z.null()])), + color: z.optional(z.union([z.string(), z.null()])), + composition: z.optional(z.union([z.string(), z.null()])), + size: z.optional(z.union([z.string(), z.null()])), + additionalInfo: z.optional(z.union([z.string(), z.null()])), + images: z.optional(z.union([z.array(zProductImageSchema), z.null()])), +}); + +/** + * UpdateProductRequest + */ +export const zUpdateProductRequest = z.object({ + entity: zUpdateProductSchema, +}); + +/** + * UpdateProductResponse + */ +export const zUpdateProductResponse = z.object({ + message: z.string(), +}); + +/** + * UpdateProductServiceSchema + */ +export const zUpdateProductServiceSchema = z.object({ + price: z.number(), + isFixedPrice: z.boolean(), +}); + +/** + * UpdateProductServiceRequest + */ +export const zUpdateProductServiceRequest = z.object({ + entity: zUpdateProductServiceSchema, +}); + +/** + * UpdateProductServiceResponse + */ +export const zUpdateProductServiceResponse = z.object({ + message: z.string(), +}); + /** * UpdateProjectSchema */ export const zUpdateProjectSchema = z.object({ name: z.optional(z.union([z.string(), z.null()])), + builtInModules: z.optional(z.array(zBuiltInModuleSchema)), }); /** @@ -288,6 +774,57 @@ export const zUpdateProjectResponse = z.object({ message: z.string(), }); +/** + * UpdateServiceSchema + */ +export const zUpdateServiceSchema = z.object({ + id: z.int(), + name: z.string(), + category: zServiceCategorySchema, + price: z.number(), + serviceType: z.int(), + priceRanges: z.array(zServicePriceRangeSchema), + cost: z.union([z.number(), z.null()]), + lexorank: z.string(), +}); + +/** + * UpdateServiceRequest + */ +export const zUpdateServiceRequest = z.object({ + entity: zUpdateServiceSchema, +}); + +/** + * UpdateServiceResponse + */ +export const zUpdateServiceResponse = z.object({ + message: z.string(), +}); + +/** + * UpdateServicesKitSchema + */ +export const zUpdateServicesKitSchema = z.object({ + name: z.string(), + serviceType: z.int(), + servicesIds: z.array(z.int()), +}); + +/** + * UpdateServicesKitRequest + */ +export const zUpdateServicesKitRequest = z.object({ + entity: zUpdateServicesKitSchema, +}); + +/** + * UpdateServicesKitResponse + */ +export const zUpdateServicesKitResponse = z.object({ + message: z.string(), +}); + /** * UpdateStatusSchema */ @@ -420,6 +957,17 @@ export const zUpdateDealData = z.object({ */ export const zUpdateDealResponse2 = zUpdateDealResponse; +export const zGetBuiltInModulesData = z.object({ + body: z.optional(z.never()), + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zGetBuiltInModulesResponse = zGetAllBuiltInModulesResponse; + export const zGetProjectsData = z.object({ body: z.optional(z.never()), path: z.optional(z.never()), @@ -517,3 +1065,321 @@ export const zUpdateStatusData = z.object({ * Successful Response */ export const zUpdateStatusResponse2 = zUpdateStatusResponse; + +export const zGetDealProductsData = z.object({ + body: z.optional(z.never()), + path: z.object({ + dealId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zGetDealProductsResponse2 = zGetDealProductsResponse; + +export const zCreateDealProductData = z.object({ + body: zCreateDealProductRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateDealProductResponse2 = zCreateDealProductResponse; + +export const zDeleteDealProductData = z.object({ + body: z.optional(z.never()), + path: z.object({ + dealId: z.int(), + productId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteDealProductResponse2 = zDeleteDealProductResponse; + +export const zUpdateDealProductData = z.object({ + body: zUpdateDealProductRequest, + path: z.object({ + dealId: z.int(), + productId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateDealProductResponse2 = zUpdateDealProductResponse; + +export const zAddKitToDealProductData = z.object({ + body: zDealProductAddKitRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zAddKitToDealProductResponse = zDealProductAddKitResponse; + +export const zCreateDealProductServiceData = z.object({ + body: zCreateProductServiceRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateDealProductServiceResponse = zCreateProductServiceResponse; + +export const zDeleteDealProductServiceData = z.object({ + body: z.optional(z.never()), + path: z.object({ + dealId: z.int(), + productId: z.int(), + serviceId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteDealProductServiceResponse = zDeleteProductServiceResponse; + +export const zUpdateDealProductServiceData = z.object({ + body: zUpdateProductServiceRequest, + path: z.object({ + dealId: z.int(), + productId: z.int(), + serviceId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateDealProductServiceResponse = zUpdateProductServiceResponse; + +export const zDuplicateProductServicesData = z.object({ + body: zProductServicesDuplicateRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDuplicateProductServicesResponse = + zProductServicesDuplicateResponse; + +export const zGetDealServicesData = z.object({ + body: z.optional(z.never()), + path: z.object({ + dealId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zGetDealServicesResponse2 = zGetDealServicesResponse; + +export const zCreateDealServiceData = z.object({ + body: zCreateDealServiceRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateDealServiceResponse2 = zCreateDealServiceResponse; + +export const zDeleteDealServiceData = z.object({ + body: z.optional(z.never()), + path: z.object({ + dealId: z.int(), + serviceId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteDealServiceResponse2 = zDeleteDealServiceResponse; + +export const zUpdateDealServiceData = z.object({ + body: zUpdateDealServiceRequest, + path: z.object({ + dealId: z.int(), + serviceId: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateDealServiceResponse2 = zUpdateDealServiceResponse; + +export const zGetProductsData = z.object({ + body: z.optional(z.never()), + path: z.optional(z.never()), + query: z.optional( + z.object({ + searchInput: z.optional(z.union([z.string(), z.null()])), + page: z.optional(z.union([z.int(), z.null()])), + itemsPerPage: z.optional(z.union([z.int(), z.null()])), + }) + ), +}); + +/** + * Successful Response + */ +export const zGetProductsResponse2 = zGetProductsResponse; + +export const zCreateProductData = z.object({ + body: zCreateProductRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateProductResponse2 = zCreateProductResponse; + +export const zDeleteProductData = z.object({ + body: z.optional(z.never()), + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteProductResponse2 = zDeleteProductResponse; + +export const zUpdateProductData = z.object({ + body: zUpdateProductRequest, + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateProductResponse2 = zUpdateProductResponse; + +export const zGetServicesData = z.object({ + body: z.optional(z.never()), + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zGetServicesResponse2 = zGetServicesResponse; + +export const zCreateServiceData = z.object({ + body: zCreateServiceRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateServiceResponse2 = zCreateServiceResponse; + +export const zDeleteServiceData = z.object({ + body: z.optional(z.never()), + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteServiceResponse2 = zDeleteServiceResponse; + +export const zUpdateServiceData = z.object({ + body: zUpdateServiceRequest, + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateServiceResponse2 = zUpdateServiceResponse; + +export const zGetServicesKitsData = z.object({ + body: z.optional(z.never()), + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zGetServicesKitsResponse = zGetServicesKitResponse; + +export const zCreateServicesKitData = z.object({ + body: zCreateServicesKitRequest, + path: z.optional(z.never()), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zCreateServicesKitResponse2 = zCreateServicesKitResponse; + +export const zDeleteServicesKitData = z.object({ + body: z.optional(z.never()), + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zDeleteServicesKitResponse2 = zDeleteServicesKitResponse; + +export const zUpdateServicesKitData = z.object({ + body: zUpdateServicesKitRequest, + path: z.object({ + pk: z.int(), + }), + query: z.optional(z.never()), +}); + +/** + * Successful Response + */ +export const zUpdateServicesKitResponse2 = zUpdateServicesKitResponse; diff --git a/src/modals/base/BaseFormModal/BaseFormModal.tsx b/src/modals/base/BaseFormModal/BaseFormModal.tsx new file mode 100644 index 0000000..859979f --- /dev/null +++ b/src/modals/base/BaseFormModal/BaseFormModal.tsx @@ -0,0 +1,63 @@ +import { ReactNode } from "react"; +import { Flex } from "@mantine/core"; +import { UseFormReturnType } from "@mantine/form"; +import BaseFormModalActions from "@/modals/base/BaseFormModal/BaseFormModalActions"; + +export type CreateProps = { + onCreate: (values: TCreate) => void; + isEditing: false; +}; + +export type EditProps = { + onChange: (values: TUpdate) => void; + entity: TEntity; + isEditing: true; +}; + +export type CreateEditFormProps< + TCreate, + TUpdate = TCreate, + TEntity = TUpdate, +> = CreateProps | EditProps; + +export type BaseFormProps = { + form: UseFormReturnType>; + onClose: () => void; + closeOnSubmit?: boolean; + children: ReactNode; +}; + +type Props = BaseFormProps & + CreateEditFormProps; + +const BaseFormModal = ( + props: Props +) => { + const { closeOnSubmit = false } = props; + + const onSubmit = (values: Partial) => { + if (props.isEditing) { + props.onChange({ ...props.entity, ...values } as TUpdate); + } else { + props.onCreate(values as TCreate); + } + + if (closeOnSubmit) { + props.form.reset(); + props.onClose(); + } + }; + + return ( +
onSubmit(values))}> + + {props.children} + + +
+ ); +}; + +export default BaseFormModal; diff --git a/src/modals/base/BaseFormModal/BaseFormModalActions.tsx b/src/modals/base/BaseFormModal/BaseFormModalActions.tsx new file mode 100644 index 0000000..c2a2b56 --- /dev/null +++ b/src/modals/base/BaseFormModal/BaseFormModalActions.tsx @@ -0,0 +1,25 @@ +import { FC } from "react"; +import { Button, Flex } from "@mantine/core"; + +type Props = { + onClose: () => void; +}; + +const BaseFormModalActions: FC = ({ onClose }) => ( + + + + +); + +export default BaseFormModalActions; diff --git a/src/modals/modals.ts b/src/modals/modals.ts index e8dd16f..8bdae40 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -2,10 +2,22 @@ import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/De import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal"; import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal"; import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal"; +import DealProductEditorModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DealProductEditorModal/DealProductEditorModal"; +import DealServiceEditorModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DealServiceEditorModal/DealServiceEditorModal"; +import DuplicateServicesModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/DuplicateServicesModal/DuplicateServicesModal"; +import ProductEditorModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductEditorModal/ProductEditorModal"; +import ProductServiceEditorModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal"; +import ServicesKitSelectModal from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ServicesKitSelectModal/ServicesKitSelectModal"; export const modals = { enterNameModal: EnterNameModal, dealsTableFiltersModal: DealsTableFiltersModal, dealsBoardFiltersModal: DealsBoardFiltersModal, dealsScheduleFiltersModal: DealsScheduleFiltersModal, + productEditorModal: ProductEditorModal, + dealProductEditorModal: DealProductEditorModal, + dealServiceEditorModal: DealServiceEditorModal, + productServiceEditorModal: ProductServiceEditorModal, + duplicateServicesModal: DuplicateServicesModal, + servicesKitSelectModal: ServicesKitSelectModal, }; diff --git a/src/modules/connectModules.tsx b/src/modules/connectModules.tsx new file mode 100644 index 0000000..2275013 --- /dev/null +++ b/src/modules/connectModules.tsx @@ -0,0 +1,13 @@ +import FulfillmentBaseTab from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab"; +import { ModuleNames } from "./modules"; +import ModulesType from "./types"; + +const connectModules = (modules: ModulesType) => { + modules[ModuleNames.FULFILLMENT_BASE].getTab = props => ( + + ); + + return modules; +}; + +export default connectModules; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.module.css b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.module.css new file mode 100644 index 0000000..14c7371 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.module.css @@ -0,0 +1,38 @@ +.container { + display: flex; + //flex-direction: column; + gap: rem(10); + max-height: 95vh; +} + +.container-disabled { +} + +.products-list { + width: 52%; + display: flex; + flex-direction: column; + gap: rem(10); + flex: 2; +} + +.card-container { + display: flex; + flex-direction: column; + gap: rem(10); + flex: 1; +} + +.card-container-wrapper { + border: dashed var(--item-border-size) var(--mantine-color-default-border); + border-radius: var(--item-border-radius); + padding: rem(10); +} + +.card-container-buttons { + gap: rem(10); + display: flex; + flex-direction: column; + margin-top: auto; + width: 100%; +} diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.tsx new file mode 100644 index 0000000..cee1278 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/FulfillmentBaseTab.tsx @@ -0,0 +1,18 @@ +import { FC } from "react"; +import { DealSchema } from "@/lib/client"; +import FulfillmentBaseTabBody from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody"; +import { FulfillmentBaseContextProvider } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext"; + +type Props = { + value: DealSchema; +}; + +const FulfillmentBaseTab: FC = ({ value }) => { + return ( + + + + ); +}; + +export default FulfillmentBaseTab; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx new file mode 100644 index 0000000..f465466 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx @@ -0,0 +1,71 @@ +import { FC } from "react"; +import { Flex, rem } from "@mantine/core"; +import DealServiceRow from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServiceRow"; +import DealServicesTitle from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTitle"; +import DealServicesTotalLabel from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTotalLabel"; +import ServicesActions from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/ServicesActions"; +import { useFulfillmentBaseContext } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext"; + +const DealServicesTable: FC = () => { + const { dealServicesList, dealServicesCrud } = useFulfillmentBaseContext(); + + // const isLocked = isDealLocked(deal); // TODO bills + + // const [currentService, setCurrentService] = useState< + // DealServiceSchema | undefined + // >(); + // const [employeesModalVisible, setEmployeesModalVisible] = useState(false); + + // const onEmployeeClick = (item: CardServiceSchema) => { + // if (!onChange) return; + // setCurrentService(item); + // setEmployeesModalVisible(true); + // }; + // const onEmployeeModalClose = () => { + // setEmployeesModalVisible(false); + // setCurrentService(undefined); + // }; + // const getCurrentEmployees = (): UserSchema[] => { + // if (!currentService) return []; + // const item = items.find( + // i => i.service.id === currentService.service.id + // ); + // if (!item) return []; + // return item.employees; + // }; + // const onEmployeesChange = (items: UserSchema[]) => { + // if (!currentService || !onChange) return; + // debouncedOnChange({ + // ...currentService, + // employees: items, + // }); + // }; + + return ( + + + + + {dealServicesList.dealServices.map(dealService => ( + + ))} + + + + + + ); +}; +export default DealServicesTable; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServiceRow.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServiceRow.tsx new file mode 100644 index 0000000..0a7a6c6 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServiceRow.tsx @@ -0,0 +1,114 @@ +import { FC } from "react"; +import { IconTrash } from "@tabler/icons-react"; +import { isNumber } from "lodash"; +import { + ActionIcon, + Divider, + Group, + NumberInput, + Stack, + Text, + Tooltip, +} from "@mantine/core"; +import { useDebouncedCallback } from "@mantine/hooks"; +import { DealServiceSchema } from "@/lib/client"; +import LockCheckbox from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox"; + +type Props = { + value: DealServiceSchema; + onChange: ( + dealId: number, + serviceId: number, + value: DealServiceSchema + ) => void; + onDelete: (value: DealServiceSchema) => void; +}; + +const DealServiceRow: FC = ({ value, onChange, onDelete }) => { + const debouncedOnChange = useDebouncedCallback( + async (item: DealServiceSchema) => { + onChange(item.dealId, item.serviceId, item); + }, + 200 + ); + + const onQuantityChange = (item: DealServiceSchema, quantity: number) => { + debouncedOnChange({ ...item, quantity }); + }; + + const onPriceChange = (item: DealServiceSchema, price: number) => { + debouncedOnChange({ + ...item, + price, + isFixedPrice: true, + }); + }; + + return ( + + + {value.service.name} + + onDelete(value)} + label="Удалить услугу"> + + + + + {/**/} + {/* onEmployeeClick(service)}*/} + {/* variant={"default"}>*/} + {/* */} + {/* */} + {/**/} + + isNumber(event) && onQuantityChange(value, event) + } + value={value.quantity} + min={1} + allowNegative={false} + /> + + isNumber(event) && onPriceChange(value, event) + } + suffix={"₽"} + value={value.price} + disabled={value.isFixedPrice} + min={1} + allowNegative={false} + rightSectionProps={{ + style: { + display: "flex", + cursor: "pointer", + pointerEvents: "auto", + }, + }} + rightSection={ + + debouncedOnChange({ + ...value, + isFixedPrice, + }) + } + /> + } + /> + + + ); +}; + +export default DealServiceRow; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTitle.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTitle.tsx new file mode 100644 index 0000000..f7eae14 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTitle.tsx @@ -0,0 +1,12 @@ +import { rem, Title } from "@mantine/core"; + +const DealServicesTitle = () => ( + + Общие услуги + +); + +export default DealServicesTitle; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTotalLabel.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTotalLabel.tsx new file mode 100644 index 0000000..befa109 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/DealServicesTotalLabel.tsx @@ -0,0 +1,26 @@ +import { useMemo } from "react"; +import { rem, Title } from "@mantine/core"; +import { useFulfillmentBaseContext } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext"; + +const DealServicesTotalLabel = () => { + const { dealServicesList } = useFulfillmentBaseContext(); + const total = useMemo( + () => + dealServicesList.dealServices.reduce( + (acc, item) => acc + item.price * item.quantity, + 0 + ), + [dealServicesList.dealServices] + ); + + return ( + + Итог: {total}₽ + + ); +}; + +export default DealServicesTotalLabel; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/ServicesActions.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/ServicesActions.tsx new file mode 100644 index 0000000..01395eb --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/components/ServicesActions.tsx @@ -0,0 +1,58 @@ +import { Button, Flex, rem } from "@mantine/core"; +import { modals } from "@mantine/modals"; +import { useFulfillmentBaseContext } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext"; + +const ServicesActions = () => { + const { dealServicesList, dealServicesCrud, deal } = + useFulfillmentBaseContext(); + + const onCreateClick = () => { + const serviceIdsToExclude = dealServicesList.dealServices.map( + service => service.service.id + ); + modals.openContextModal({ + modal: "dealServiceEditorModal", + innerProps: { + onCreate: values => + dealServicesCrud.onCreate({ ...values, dealId: deal.id }), + serviceIdsToExclude, + isEditing: false, + }, + withCloseButton: false, + }); + }; + + // const onAddKitClick = () => { + // if (!onKitAdd) return; + // modals.openContextModal({ + // modal: "servicesKitSelectModal", + // innerProps: { + // onSelect: onKitAdd, + // serviceType: ServiceType.DEAL_SERVICE, + // }, + // withCloseButton: false, + // }); + // }; + + return ( + + + {/**/} + {/* Добавить набор услуг*/} + {/**/} + + ); +}; + +export default ServicesActions; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody.tsx new file mode 100644 index 0000000..f2f63bc --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/FulfillmentBaseTabBody/FulfillmentBaseTabBody.tsx @@ -0,0 +1,34 @@ +import { Flex, ScrollArea, Stack } from "@mantine/core"; +import DealServicesTable from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable"; +import ProductsActions from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductsActions/ProductsActions"; +import ProductView from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView"; +import { useFulfillmentBaseContext } from "../../contexts/FulfillmentBaseContext"; + +const FulfillmentBaseTabBody = () => { + const { dealProductsList } = useFulfillmentBaseContext(); + + return ( + + + + {dealProductsList.dealProducts.map((dealProduct, index) => ( + + ))} + + + + + + + + ); +}; + +export default FulfillmentBaseTabBody; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/GeneralDataForm/GeneralDataForm.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/GeneralDataForm/GeneralDataForm.tsx new file mode 100644 index 0000000..6e948b1 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/GeneralDataForm/GeneralDataForm.tsx @@ -0,0 +1,115 @@ +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"; +import { useSelector } from "react-redux"; +import { RootState } from "../../../../../../redux/store.ts"; + + +type GeneralDataFormType = { + shippingWarehouse?: ShippingWarehouseSchema | null | string; + isServicesProfitAccounted: boolean; +} + +const GeneralDataForm = () => { + const { selectedCard: card, refetchCard } = useCardPageContext(); + const { isDealsViewer } = useSelector((state: RootState) => state.auth); + if (!card) return <>; + + const [initialValues, setInitialValues] = useState(card); + + const form = useForm({ + 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 ( +
onSubmit(values))}> + + { + if (isShippingWarehouse(event)) { + form.getInputProps( + "shippingWarehouse", + ).onChange(event.name); + return; + } + form.getInputProps( + "shippingWarehouse", + ).onChange(event); + }} + readOnly={isDealsViewer} + /> + {!isDealsViewer && ( + <> + + + + )} + +
+ ); +}; + +export default GeneralDataForm; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox.tsx new file mode 100644 index 0000000..029fff4 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/LockCheckbox/LockCheckbox.tsx @@ -0,0 +1,28 @@ +import { FC } from "react"; +import { IconLock, IconLockOpen } from "@tabler/icons-react"; +import { ActionIcon, CheckboxProps, Tooltip } from "@mantine/core"; + +type RestProps = { + value: boolean; + onChange: (value: boolean) => void; +}; + +type Props = Omit & RestProps; + +const LockCheckbox: FC = props => { + const getIcon = () => (props.value ? : ); + + const handleChange = () => props.onChange(!props.value); + + return ( + + + {getIcon()} + + + ); +}; + +export default LockCheckbox; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PaymentLinkButton/PaymentLinkButton.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PaymentLinkButton/PaymentLinkButton.tsx new file mode 100644 index 0000000..87cec49 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PaymentLinkButton/PaymentLinkButton.tsx @@ -0,0 +1,68 @@ +import { CardSchema } from "../../../../../../client"; +import ButtonCopy from "../../../../../../components/ButtonCopy/ButtonCopy.tsx"; +import { ButtonCopyControlled } from "../../../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx"; +import { getCurrentDateTimeForFilename } from "../../../../../../shared/lib/date.ts"; +import FileSaver from "file-saver"; +import { Button, Popover, Stack } from "@mantine/core"; + +type Props = { + card: CardSchema; +} + +const PaymentLinkButton = ({ card }: Props) => { + if ((!card.billRequests || card.billRequests.length === 0) && (!card?.group?.billRequests || card?.group?.billRequests.length === 0)) { + return ( + { + const date = + getCurrentDateTimeForFilename(); + FileSaver.saveAs( + `${import.meta.env.VITE_API_URL}/card/billing-document/${card.id}`, + `bill_${card.id}_${date}.pdf`, + ); + }} + copied={false} + onCopiedLabel={"Ссылка скопирована в буфер обмена"} + > + Ссылка на оплату (PDF) + + ); + } + + const requests = (card?.group ? card?.group?.billRequests : card.billRequests) ?? []; + const urls = requests.map(request => request.pdfUrl).filter(url => url !== null); + + if (urls.length === 1) { + return ( + + Ссылка на оплату + + ); + } + + return ( + + + + + + + {urls.map((url, i) => ( + + {`Ссылка на оплату (часть ${String(i + 1)})`} + + ))} + + + + ); +}; + +export default PaymentLinkButton; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PrintDealBarcodesButton/PrintDealBarcodesButton.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PrintDealBarcodesButton/PrintDealBarcodesButton.tsx new file mode 100644 index 0000000..a465329 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/PrintDealBarcodesButton/PrintDealBarcodesButton.tsx @@ -0,0 +1,63 @@ +import { ActionIcon, Group, Tooltip } from "@mantine/core"; +import styles from "../../../../../../pages/CardsPage/ui/CardsPage.module.css"; +import { CardSchema, CardService } from "../../../../../../client"; +import { base64ToBlob } from "../../../../../../shared/lib/utils.ts"; +import { notifications } from "../../../../../../shared/lib/notifications.ts"; +import { IconBarcode, IconPrinter } from "@tabler/icons-react"; + + +type Props = { + card: CardSchema; +} + +const PrintDealBarcodesButton = ({ card }: Props) => { + return ( + + + { + const response = + await CardService.getCardProductsBarcodesPdf({ + requestBody: { + cardId: card.id, + }, + }); + const pdfBlob = base64ToBlob( + response.base64String, + response.mimeType, + ); + const pdfUrl = URL.createObjectURL(pdfBlob); + const pdfWindow = window.open(pdfUrl); + if (!pdfWindow) { + notifications.error({ message: "Ошибка" }); + return; + } + pdfWindow.onload = () => { + pdfWindow.print(); + }; + }} + variant={"default"}> + + + + + { + const pdfWindow = window.open( + `${import.meta.env.VITE_API_URL}/card/tech-spec/${card.id}`, + ); + if (!pdfWindow) return; + pdfWindow.print(); + }} + variant={"default"}> + + + + + ); +}; + +export default PrintDealBarcodesButton; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/ProductImageDropzone.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/ProductImageDropzone.tsx new file mode 100644 index 0000000..31ab76b --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/ProductImageDropzone.tsx @@ -0,0 +1,68 @@ +import { FC } from "react"; +import { DropzoneProps, FileWithPath } from "@mantine/dropzone"; +import ImageDropzone from "@/components/ui/ImageDropzone/ImageDropzone"; +import { notifications } from "@/lib/notifications"; +import BaseFormInputProps from "@/utils/baseFormInputProps"; +import useImageDropzone from "./useImageDropzone"; + +interface RestProps { + imageUrlInputProps?: BaseFormInputProps; + productId?: number; +} + +type Props = Omit & RestProps; + +const ProductImageDropzone: FC = ({ + imageUrlInputProps, + productId, +}: Props) => { + const imageDropzoneProps = useImageDropzone({ + imageUrlInputProps, + }); + + const onDrop = (files: FileWithPath[]) => { + if (!productId || !imageUrlInputProps) return; + if (files.length > 1) { + notifications.error({ message: "Прикрепите одно изображение" }); + return; + } + const { setIsLoading, setShowDropzone } = imageDropzoneProps; + const file = files[0]; + + setIsLoading(true); + + // TODO SEND REQUEST + + // ProductService.uploadProductImage({ + // productId, + // formData: { + // upload_file: file, + // }, + // }) + // .then(({ ok, message, imageUrl }) => { + // notifications.guess(ok, { message }); + // setIsLoading(false); + // + // if (!ok || !imageUrl) { + // setShowDropzone(true); + // return; + // } + // imageUrlInputProps?.onChange(imageUrl); + // setShowDropzone(false); + // }) + // .catch(error => { + // notifications.error({ message: error.toString() }); + // setShowDropzone(true); + // setIsLoading(false); + // }); + }; + + return ( + + ); +}; + +export default ProductImageDropzone; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/useImageDropzone.ts b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/useImageDropzone.ts new file mode 100644 index 0000000..db364b7 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductImageDropzone/useImageDropzone.ts @@ -0,0 +1,27 @@ +import { useState } from "react"; +import BaseFormInputProps from "@/utils/baseFormInputProps"; + +type Props = { + imageUrlInputProps?: BaseFormInputProps; +}; + +const useImageDropzone = ({ imageUrlInputProps }: Props) => { + const [showDropzone, setShowDropzone] = useState( + !( + typeof imageUrlInputProps?.value === "string" && + imageUrlInputProps.value.trim() !== "" + ) + ); + + const [isLoading, setIsLoading] = useState(false); + + return { + showDropzone, + setShowDropzone, + isLoading, + setIsLoading, + imageUrlInputProps, + }; +}; + +export default useImageDropzone; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/ProductSelect.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/ProductSelect.tsx new file mode 100644 index 0000000..6c97d75 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/ProductSelect.tsx @@ -0,0 +1,55 @@ +import { FC, useState } from "react"; +import { omit } from "lodash"; +import { Loader, OptionsFilter } from "@mantine/core"; +import { useDebouncedValue } from "@mantine/hooks"; +import ObjectSelect, { + ObjectSelectProps, +} from "@/components/selects/ObjectSelect/ObjectSelect"; +import { ProductSchema } from "@/lib/client"; +import useProductsList from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/hooks/lists/useProductsList"; +import renderProductOption from "./utils/renderProductOption"; + +type RestProps = { + clientId: number; +}; + +const MAX_PRODUCTS = 200; + +type Props = Omit, "data"> & RestProps; + +const ProductSelect: FC = (props: Props) => { + const [searchValue, setSearchValue] = useState(""); + const [debounced] = useDebouncedValue(searchValue, 500); + const { products, isLoading } = useProductsList({ + // clientId: props.clientId, + searchInput: debounced, + page: 0, + itemsPerPage: MAX_PRODUCTS, + }); + const restProps = omit(props, ["clientId"]); + + const optionsFilter: OptionsFilter = ({ options }) => options; + const setSearchValueImpl = (value: string) => { + const names = products.map(product => product.name); + if (names.includes(value)) return; + setSearchValue(value); + }; + + return ( + + ) : null + } + onSearchChange={setSearchValueImpl} + renderOption={renderProductOption(products)} + searchable + {...restProps} + data={products} + filter={optionsFilter} + /> + ); +}; + +export default ProductSelect; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/utils/renderProductOption.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/utils/renderProductOption.tsx new file mode 100644 index 0000000..55b9076 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductSelect/utils/renderProductOption.tsx @@ -0,0 +1,51 @@ +import { + ComboboxItem, + ComboboxLikeRenderOptionInput, + SelectProps, + Tooltip, +} from "@mantine/core"; +import { ProductSchema } from "@/lib/client"; +import ProductFieldsList from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductFieldsList"; + +const renderProductOption = ( + products: ProductSchema[] +): SelectProps["renderOption"] => { + return (item: ComboboxLikeRenderOptionInput) => { + const product = products.find( + product => product.id === Number(item.option.value) + ); + if (!product) return item.option.label; + // const imageUrl = + // product.images && product.images[0] + // ? product.images[0].imageUrl + // : undefined; + + return ( + + + {/*{imageUrl && (*/} + {/* */} + {/*)}*/} + + }> +
+ {product.name} +
+ {/*{product.barcodes && (*/} + {/* {product.barcodes[0]}*/} + {/*)}*/} +
+
+ ); + }; +}; + +export default renderProductOption; diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.module.css b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.module.css new file mode 100644 index 0000000..5e37bb4 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.module.css @@ -0,0 +1,36 @@ +.container { + display: flex; + border: dashed var(--item-border-size) var(--mantine-color-default-border); + border-radius: var(--item-border-radius); + gap: rem(20); + padding: rem(10); + margin-bottom: rem(10); + flex: 1; +} + +.image-container { + display: flex; + max-height: rem(250); + max-width: rem(250); + height: 100%; +} + +.services-container { + width: 100%; + display: flex; + flex-direction: column; + gap: rem(10); + flex: 1; +} + +.data-container { + max-width: rem(250); + display: flex; + flex-direction: column; + gap: rem(10); + flex: 1; +} + +.attributes-container { + overflow-wrap: break-word; +} diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.tsx new file mode 100644 index 0000000..13baac5 --- /dev/null +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/ProductView.tsx @@ -0,0 +1,156 @@ +import { FC } from "react"; +import { isNumber } from "lodash"; +import { + Box, + Card, + Image, + NumberInput, + rem, + Stack, + Textarea, + Title, +} from "@mantine/core"; +import { useDebouncedCallback } from "@mantine/hooks"; +import { modals } from "@mantine/modals"; +import { + addKitToDealProduct, + DealProductSchema, + duplicateProductServices, + ServicesKitSchema, +} from "@/lib/client"; +import ProductFieldsList from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductFieldsList"; +import ProductViewActions from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/components/ProductViewActions"; +import { useFulfillmentBaseContext } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/contexts/FulfillmentBaseContext"; +import { ServiceType } from "@/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/types/service"; +import ProductServicesTable from "./components/ProductServicesTable"; + +type Props = { + dealProduct: DealProductSchema; +}; + +const ProductView: FC = ({ dealProduct }) => { + const { dealProductsCrud, deal, dealProductsList } = + useFulfillmentBaseContext(); + + const debouncedOnChange = useDebouncedCallback( + (newValues: Partial) => { + dealProductsCrud.onUpdate( + dealProduct.dealId, + dealProduct.productId, + { + ...dealProduct, + ...newValues, + } + ); + }, + 200 + ); + + const duplicateServices = ( + sourceDealProduct: DealProductSchema, + targetDealProducts: DealProductSchema[] + ) => { + duplicateProductServices({ + body: { + dealId: deal.id, + sourceDealProductId: sourceDealProduct.productId, + targetDealProductIds: targetDealProducts.map(p => p.productId), + }, + }) + .then(() => dealProductsList.refetch()) + .catch(err => console.error(err)); + }; + + const onDuplicateServices = (sourceDealProduct: DealProductSchema) => { + modals.openContextModal({ + modal: "duplicateServicesModal", + title: "Дублирование услуг", + size: "lg", + innerProps: { + dealProducts: dealProductsList.dealProducts, + sourceDealProduct, + duplicateServices, + }, + withCloseButton: false, + }); + }; + + const onServicesKitAdd = (servicesKit: ServicesKitSchema) => { + addKitToDealProduct({ + body: { + dealId: dealProduct.dealId, + productId: dealProduct.productId, + kitId: servicesKit.id, + }, + }) + .then(() => dealProductsList.refetch()) + .catch(err => console.error(err)); + }; + + const onAddKitClick = () => { + modals.openContextModal({ + modal: "servicesKitSelectModal", + innerProps: { + onSelect: onServicesKitAdd, + serviceType: ServiceType.PRODUCT_SERVICE, + }, + withCloseButton: false, + }); + }; + + return ( + + + + {dealProduct.product.name} + + {/**/} + {/* Штрихкоды:*/} + {/*{value.product.barcodes.join(", ")}*/} + {/**/} + + + isNumber(quantity) && debouncedOnChange({ quantity }) + } + placeholder={"Введите количество товара"} + /> +