From 0805a86335139746888f329fe9ff947dfff4e085 Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Thu, 18 Sep 2025 17:53:26 +0400 Subject: [PATCH] feat: module dependencies --- .../tabs/ModulesTab/ModulesTab.tsx | 16 +++++-- .../ModulesTab/components/ModulesTable.tsx | 19 +++++---- .../hooks/useModulesTableColumns.tsx | 30 +++++++++++-- .../ModulesTab/utils/resolveDependencies.ts | 22 ++++++++++ src/hooks/lists/useBuiltInModulesList.ts | 13 ++++++ src/lib/client/@tanstack/react-query.gen.ts | 4 +- src/lib/client/sdk.gen.ts | 2 +- src/lib/client/types.gen.ts | 42 +++++++++++++++++-- src/lib/client/zod.gen.ts | 33 +++++++++++++-- .../DealServicesTable/DealServicesTable.tsx | 30 ------------- .../components/DealServiceRow.tsx | 5 --- .../components/ProductServicesTable.tsx | 30 ------------- .../hooks/useProductServicesTableColumns.tsx | 9 ---- .../ProductServiceEditorModal.tsx | 1 - src/modules/modules.tsx | 7 ---- .../templates/modulesFileTemplate.hbs | 7 ---- src/modules/types.tsx | 2 - 17 files changed, 153 insertions(+), 119 deletions(-) create mode 100644 src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/utils/resolveDependencies.ts create mode 100644 src/hooks/lists/useBuiltInModulesList.ts diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx index e9dbe8a..2ac6183 100644 --- a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/ModulesTab.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; -import { isEqual } from "lodash"; import { Button, Stack } from "@mantine/core"; import { useForm } from "@mantine/form"; +import resolveDependencies from "@/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/utils/resolveDependencies"; import { ProjectSchema } from "@/lib/client"; import ModulesTable from "./components/ModulesTable"; @@ -16,8 +16,16 @@ export const ModulesTab: FC = ({ value, onChange }) => { }); const onSubmit = (values: ProjectSchema) => { - onChange(values); - form.setInitialValues(values); + const modulesWithDependencies = resolveDependencies( + values.builtInModules + ); + const updatedValues = { + ...values, + builtInModules: modulesWithDependencies, + }; + form.setValues(updatedValues); + form.resetDirty(); + onChange(updatedValues); }; return ( @@ -32,7 +40,7 @@ export const ModulesTab: FC = ({ value, onChange }) => { diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx index 85ad395..3ec35bc 100644 --- a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/components/ModulesTable.tsx @@ -1,28 +1,29 @@ -import { FC, useRef } from "react"; +import { FC } 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"; +import useBuiltInModulesList from "@/hooks/lists/useBuiltInModulesList"; +import { BuiltInModuleSchemaOutput } from "@/lib/client"; type Props = { - selectedRecords: BuiltInModuleSchema[]; - onSelectedRecordsChange: (records: BuiltInModuleSchema[]) => void; + selectedRecords: BuiltInModuleSchemaOutput[]; + onSelectedRecordsChange: (records: BuiltInModuleSchemaOutput[]) => void; }; const ModulesTable: FC = props => { const columns = useModulesTableColumns(); - const modules = useRef( - Object.values(MODULES).map(module => module.modelData) - ); + const { builtInModules } = useBuiltInModulesList(); return ( diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx index 7b75d03..0a84e64 100644 --- a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/hooks/useModulesTableColumns.tsx @@ -1,6 +1,8 @@ import { useMemo } from "react"; +import { IconInfoCircle } from "@tabler/icons-react"; import { DataTableColumn } from "mantine-datatable"; -import { BuiltInModuleSchema } from "@/lib/client"; +import { em, Group, Text, Tooltip } from "@mantine/core"; +import { BuiltInModuleSchemaOutput } from "@/lib/client"; const useModulesTableColumns = () => { return useMemo( @@ -9,14 +11,34 @@ const useModulesTableColumns = () => { { accessor: "label", title: "Название", - width: "30%", + width: "20%", }, { title: "Описание", accessor: "description", - width: "70%", + width: "50%", }, - ] as DataTableColumn[], + { + title: ( + + Зависит от модулей + + + + + ), + accessor: "dependsOn", + width: "30%", + render: module => ( + + {module.dependsOn?.map(m => m.label).join(", ")} + + ), + }, + ] as DataTableColumn[], [] ); }; diff --git a/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/utils/resolveDependencies.ts b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/utils/resolveDependencies.ts new file mode 100644 index 0000000..12d0524 --- /dev/null +++ b/src/app/deals/drawers/ProjectEditorDrawer/tabs/ModulesTab/utils/resolveDependencies.ts @@ -0,0 +1,22 @@ +import { uniqBy } from "lodash"; +import { BuiltInModuleSchemaOutput } from "@/lib/client"; + +const resolveDependencies = ( + modules: BuiltInModuleSchemaOutput[] +): BuiltInModuleSchemaOutput[] => { + const resolved = new Set(); + const result: BuiltInModuleSchemaOutput[] = []; + + const addModule = (module: BuiltInModuleSchemaOutput) => { + if (resolved.has(module.id)) return; + resolved.add(module.id); + + module.dependsOn.forEach(addModule); + result.push(module); + }; + + modules.forEach(addModule); + return uniqBy(result, "id"); +}; + +export default resolveDependencies; diff --git a/src/hooks/lists/useBuiltInModulesList.ts b/src/hooks/lists/useBuiltInModulesList.ts new file mode 100644 index 0000000..825a881 --- /dev/null +++ b/src/hooks/lists/useBuiltInModulesList.ts @@ -0,0 +1,13 @@ +import { useQuery } from "@tanstack/react-query"; +import { getBuiltInModulesOptions } from "@/lib/client/@tanstack/react-query.gen"; + +const useBuiltInModulesList = () => { + const { data, refetch } = useQuery(getBuiltInModulesOptions()); + + return { + builtInModules: data?.items ?? [], + refetch, + }; +}; + +export default useBuiltInModulesList; diff --git a/src/lib/client/@tanstack/react-query.gen.ts b/src/lib/client/@tanstack/react-query.gen.ts index 855d22c..fb794c2 100644 --- a/src/lib/client/@tanstack/react-query.gen.ts +++ b/src/lib/client/@tanstack/react-query.gen.ts @@ -1276,7 +1276,7 @@ export const addKitToDealQueryKey = (options: Options) => createQueryKey("addKitToDeal", options); /** - * Add Kit To Deal Product + * Add Kit To Deal */ export const addKitToDealOptions = (options: Options) => { return queryOptions({ @@ -1294,7 +1294,7 @@ export const addKitToDealOptions = (options: Options) => { }; /** - * Add Kit To Deal Product + * Add Kit To Deal */ export const addKitToDealMutation = ( options?: Partial> diff --git a/src/lib/client/sdk.gen.ts b/src/lib/client/sdk.gen.ts index 39db30b..ba087dc 100644 --- a/src/lib/client/sdk.gen.ts +++ b/src/lib/client/sdk.gen.ts @@ -990,7 +990,7 @@ export const updateDealService = ( }; /** - * Add Kit To Deal Product + * Add Kit To Deal */ export const addKitToDeal = ( options: Options diff --git a/src/lib/client/types.gen.ts b/src/lib/client/types.gen.ts index 5a72ac2..d05c5a9 100644 --- a/src/lib/client/types.gen.ts +++ b/src/lib/client/types.gen.ts @@ -25,7 +25,7 @@ export type BoardSchema = { /** * BuiltInModuleSchema */ -export type BuiltInModuleSchema = { +export type BuiltInModuleSchemaInput = { /** * Id */ @@ -46,6 +46,40 @@ export type BuiltInModuleSchema = { * Description */ description: string; + /** + * Dependson + */ + dependsOn: Array; +}; + +/** + * BuiltInModuleSchema + */ +export type BuiltInModuleSchemaOutput = { + /** + * Id + */ + id: number; + /** + * Key + */ + key: string; + /** + * Label + */ + label: string; + /** + * Iconname + */ + iconName: string; + /** + * Description + */ + description: string; + /** + * Dependson + */ + dependsOn: Array; }; /** @@ -690,7 +724,7 @@ export type GetAllBuiltInModulesResponse = { /** * Items */ - items: Array; + items: Array; }; /** @@ -938,7 +972,7 @@ export type ProjectSchema = { /** * Builtinmodules */ - builtInModules: Array; + builtInModules: Array; }; /** @@ -1316,7 +1350,7 @@ export type UpdateProjectSchema = { /** * Builtinmodules */ - builtInModules?: Array; + builtInModules?: Array; }; /** diff --git a/src/lib/client/zod.gen.ts b/src/lib/client/zod.gen.ts index c1f98d1..8b79751 100644 --- a/src/lib/client/zod.gen.ts +++ b/src/lib/client/zod.gen.ts @@ -15,12 +15,37 @@ export const zBoardSchema = z.object({ /** * BuiltInModuleSchema */ -export const zBuiltInModuleSchema = z.object({ +export const zBuiltInModuleSchemaInput = z.object({ id: z.int(), key: z.string(), label: z.string(), iconName: z.string(), description: z.string(), + get dependsOn() { + return z.array( + z.lazy((): any => { + return zBuiltInModuleSchemaInput; + }) + ); + }, +}); + +/** + * BuiltInModuleSchema + */ +export const zBuiltInModuleSchemaOutput = z.object({ + id: z.int(), + key: z.string(), + label: z.string(), + iconName: z.string(), + description: z.string(), + get dependsOn() { + return z.array( + z.lazy((): any => { + return zBuiltInModuleSchemaOutput; + }) + ); + }, }); /** @@ -304,7 +329,7 @@ export const zCreateProjectRequest = z.object({ export const zProjectSchema = z.object({ id: z.int(), name: z.string(), - builtInModules: z.array(zBuiltInModuleSchema), + builtInModules: z.array(zBuiltInModuleSchemaOutput), }); /** @@ -507,7 +532,7 @@ export const zDeleteStatusResponse = z.object({ * GetAllBuiltInModulesResponse */ export const zGetAllBuiltInModulesResponse = z.object({ - items: z.array(zBuiltInModuleSchema), + items: z.array(zBuiltInModuleSchemaOutput), }); /** @@ -772,7 +797,7 @@ export const zUpdateProductServiceResponse = z.object({ */ export const zUpdateProjectSchema = z.object({ name: z.optional(z.union([z.string(), z.null()])), - builtInModules: z.optional(z.array(zBuiltInModuleSchema)), + builtInModules: z.optional(z.array(zBuiltInModuleSchemaInput)), }); /** diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx index f465466..7e24992 100644 --- a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/DealServicesTable/DealServicesTable.tsx @@ -11,36 +11,6 @@ const DealServicesTable: FC = () => { // 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 ( = ({ value, onChange, onDelete }) => { tipLabel={"Удалить услугу"}> - {/**/} - {/* onEmployeeClick(service)}>*/} - {/* */} - {/**/} - {/**/} = ({ onChange, }); - // const [currentService, setCurrentService] = useState< - // ProductServiceSchema | undefined - // >(); - // const [employeesModalVisible, setEmployeesModalVisible] = useState(false); - const onCreateClick = () => { const excludeServiceIds = dealProduct.productServices.map( productService => productService.service.id @@ -80,31 +75,6 @@ const ProductServicesTable: FC = ({ }); }; - // const onEmployeeClick = (item: CardProductServiceSchema) => { - // 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; - // onChange({ - // ...currentService, - // employees: items, - // }); - // }; - const isEmptyTable = dealProduct.productServices.length === 0; return ( diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns.tsx index 901eb33..b5098df 100644 --- a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns.tsx +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/components/ProductView/hooks/useProductServicesTableColumns.tsx @@ -46,15 +46,6 @@ const useProductServicesTableColumns = ({ onClick={() => onChange(dealProductService)}> - {/**/} - {/* */} - {/* onEmployeeClick(row.original)*/} - {/* }*/} - {/* variant={"default"}>*/} - {/* */} - {/* */} - {/**/} ), }, diff --git a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal.tsx b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal.tsx index ab98b4e..a6e0321 100644 --- a/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal.tsx +++ b/src/modules/dealModules/dealEditorTabs/FulfillmentBaseTab/modals/ProductServiceEditorModal/ProductServiceEditorModal.tsx @@ -38,7 +38,6 @@ const ProductServiceEditorModal = ({ service: undefined, serviceId: undefined, price: undefined, - // employees: [], isFixedPrice: false, }; diff --git a/src/modules/modules.tsx b/src/modules/modules.tsx index 2a6a767..b432730 100644 --- a/src/modules/modules.tsx +++ b/src/modules/modules.tsx @@ -15,13 +15,6 @@ const modules: ModulesType = { key: "fulfillment_base", icon: , }, - modelData: { - id: 1, - key: "fulfillment_base", - label: "Фулфиллмент", - iconName: "IconBox", - description: "Создание товаров и услуг, их привязка к сделкам", - }, }, }; diff --git a/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs b/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs index 5643c8a..05a61bb 100644 --- a/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs +++ b/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs @@ -20,13 +20,6 @@ const modules: ModulesType = { key: "{{this.key}}", icon: {{#if this.iconName}}<{{this.iconName}} />{{else}}None{{/if}}, }, - modelData: { - id: {{this.id}}, - key: "{{this.key}}", - label: "{{this.label}}", - iconName: "{{this.iconName}}", - description: "{{this.description}}", - }, }, {{/each}} }; diff --git a/src/modules/types.tsx b/src/modules/types.tsx index aec2d61..e6f392e 100644 --- a/src/modules/types.tsx +++ b/src/modules/types.tsx @@ -1,5 +1,4 @@ import { ReactNode } from "react"; -import { BuiltInModuleSchema } from "@/lib/client"; export type Module = { renderInfo: { @@ -7,7 +6,6 @@ export type Module = { key: string; icon: ReactNode; }; - modelData: BuiltInModuleSchema; getTab?: (props: any) => ReactNode; };