diff --git a/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx b/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx index 6271ae1..76db146 100644 --- a/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx +++ b/src/app/deals/drawers/DealEditorDrawer/components/DealEditorBody.tsx @@ -74,7 +74,7 @@ const DealEditorBody: FC = props => { value={module.key}> diff --git a/src/app/deals/drawers/DealEditorDrawer/tabs/CustomTab/CustomTab.tsx b/src/app/deals/drawers/DealEditorDrawer/tabs/CustomTab/CustomTab.tsx index f6adbce..eae0aec 100644 --- a/src/app/deals/drawers/DealEditorDrawer/tabs/CustomTab/CustomTab.tsx +++ b/src/app/deals/drawers/DealEditorDrawer/tabs/CustomTab/CustomTab.tsx @@ -1,147 +1,21 @@ -import React, { - FC, - ReactNode, - useCallback, - useEffect, - useMemo, - useState, -} from "react"; -import { Flex, Group } from "@mantine/core"; -import AttributeValueInput from "@/app/deals/drawers/DealEditorDrawer/components/AttributeValueInput"; -import useDealAttributeValuesActions from "@/app/deals/drawers/DealEditorDrawer/hooks/useDealAttributeValuesActions"; -import FormFlexRow from "@/components/ui/FormFlexRow/FormFlexRow"; -import InlineButton from "@/components/ui/InlineButton/InlineButton"; -import { - DealModuleAttributeSchema, - DealSchema, - ModuleSchemaOutput, - UpdateDealModuleAttributeSchema, -} from "@/lib/client"; +import React, { FC } from "react"; +import AttributeEditor from "@/components/ui/AttributesEditor/AttributesEditor"; +import { DealSchema } from "@/lib/client"; type Props = { - module: ModuleSchemaOutput; + moduleId: number; deal: DealSchema; }; -type AttrInfo = { - value?: any; - isApplicableToGroup: boolean; -}; - -const CustomTab: FC = ({ module, deal }) => { - const { dealAttributes, updateAttributeValues } = - useDealAttributeValuesActions({ - moduleId: module.id, - dealId: deal.id, - }); - - const [attributeValuesMap, setAttributeValuesMap] = useState< - Map - >(new Map()); - const [attributeErrorsMap, setAttributeErrorsMap] = useState< - Map - >(new Map()); - - useEffect(() => { - const values = new Map(); - for (const dealAttr of dealAttributes) { - values.set(dealAttr.attributeId, { - ...dealAttr, - value: dealAttr.value, - }); - } - setAttributeValuesMap(values); - }, [dealAttributes]); - - const onSubmit = () => { - let isErrorFound = false; - for (const attr of dealAttributes) { - const value = attributeValuesMap.get(attr.attributeId); - if (!attr.isNullable && (value === null || value === undefined)) { - attributeErrorsMap.set(attr.attributeId, "Обязательное поле"); - isErrorFound = true; - } - } - setAttributeErrorsMap(new Map(attributeErrorsMap)); - if (isErrorFound) return; - - const attributeValues: UpdateDealModuleAttributeSchema[] = - attributeValuesMap - .entries() - .map( - ([attributeId, info]) => - ({ - attributeId, - ...info, - }) as UpdateDealModuleAttributeSchema - ) - .toArray(); - - updateAttributeValues(attributeValues); - }; - - const getAttributeElement = useCallback( - (attribute: DealModuleAttributeSchema) => ( - { - attributeValuesMap.set(attribute.attributeId, { - ...attribute, - value, - }); - setAttributeValuesMap(new Map(attributeValuesMap)); - attributeErrorsMap.delete(attribute.attributeId); - setAttributeErrorsMap(new Map(attributeErrorsMap)); - }} - style={{ flex: 1 }} - error={attributeErrorsMap.get(attribute.attributeId)} - /> - ), - [attributeValuesMap, attributeErrorsMap] - ); - - const attributesRows = useMemo(() => { - if (!dealAttributes) return []; - const boolAttributes = dealAttributes.filter( - a => a.type.type === "bool" - ); - const otherAttributes = dealAttributes.filter( - a => a.type.type !== "bool" - ); - - const rows: ReactNode[] = []; - for (let i = 0; i < otherAttributes.length; i += 2) { - const rightIdx = i + 1; - - rows.push( - - {getAttributeElement(otherAttributes[i])} - {rightIdx < otherAttributes.length && - getAttributeElement(otherAttributes[rightIdx])} - - ); - } - - for (const attr of boolAttributes) { - rows.push(getAttributeElement(attr)); - } - - return rows; - }, [dealAttributes, getAttributeElement]); - +const CustomTab: FC = props => { return ( - - {attributesRows} - - Сохранить - - + ); }; diff --git a/src/components/ui/AttributesEditor/AttributesEditor.tsx b/src/components/ui/AttributesEditor/AttributesEditor.tsx new file mode 100644 index 0000000..d34474d --- /dev/null +++ b/src/components/ui/AttributesEditor/AttributesEditor.tsx @@ -0,0 +1,169 @@ +import React, { + CSSProperties, + FC, + ReactNode, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; +import { Flex, Group } from "@mantine/core"; +import AttributeValueInput from "@/app/deals/drawers/DealEditorDrawer/components/AttributeValueInput"; +import useDealAttributeValuesActions from "@/components/ui/AttributesEditor/useDealAttributeValuesActions"; +import FormFlexRow from "@/components/ui/FormFlexRow/FormFlexRow"; +import InlineButton from "@/components/ui/InlineButton/InlineButton"; +import { + DealModuleAttributeSchema, + DealSchema, + UpdateDealModuleAttributeSchema, +} from "@/lib/client"; + +type Props = { + moduleId: number; + deal: DealSchema; + containerStyle?: CSSProperties; + buttonContainerStyle?: CSSProperties; + buttonStyle?: CSSProperties; + attributesInTwoColumns?: boolean; +}; + +type AttrInfo = { + value?: any; + isApplicableToGroup: boolean; +}; + +const AttributeEditor: FC = ({ + moduleId, + deal, + containerStyle, + buttonContainerStyle, + buttonStyle, + attributesInTwoColumns = true, +}) => { + const { dealAttributes, updateAttributeValues } = + useDealAttributeValuesActions({ + moduleId, + dealId: deal.id, + }); + + const [attributeValuesMap, setAttributeValuesMap] = useState< + Map + >(new Map()); + const [attributeErrorsMap, setAttributeErrorsMap] = useState< + Map + >(new Map()); + + useEffect(() => { + const values = new Map(); + for (const dealAttr of dealAttributes) { + values.set(dealAttr.attributeId, { + ...dealAttr, + value: dealAttr.value, + }); + } + setAttributeValuesMap(values); + }, [dealAttributes]); + + const onSubmit = () => { + let isErrorFound = false; + for (const attr of dealAttributes) { + const value = attributeValuesMap.get(attr.attributeId); + if (!attr.isNullable && (value === null || value === undefined)) { + attributeErrorsMap.set(attr.attributeId, "Обязательное поле"); + isErrorFound = true; + } + } + setAttributeErrorsMap(new Map(attributeErrorsMap)); + if (isErrorFound) return; + + const attributeValues: UpdateDealModuleAttributeSchema[] = + attributeValuesMap + .entries() + .map( + ([attributeId, info]) => + ({ + attributeId, + ...info, + }) as UpdateDealModuleAttributeSchema + ) + .toArray(); + + updateAttributeValues(attributeValues); + }; + + const getAttributeElement = useCallback( + (attribute: DealModuleAttributeSchema) => ( + { + attributeValuesMap.set(attribute.attributeId, { + ...attribute, + value, + }); + setAttributeValuesMap(new Map(attributeValuesMap)); + attributeErrorsMap.delete(attribute.attributeId); + setAttributeErrorsMap(new Map(attributeErrorsMap)); + }} + style={{ flex: 1 }} + error={attributeErrorsMap.get(attribute.attributeId)} + /> + ), + [attributeValuesMap, attributeErrorsMap] + ); + + const attributesRows = useMemo(() => { + if (!dealAttributes) return []; + const boolAttributes = dealAttributes.filter( + a => a.type.type === "bool" + ); + const otherAttributes = dealAttributes.filter( + a => a.type.type !== "bool" + ); + + const rows: ReactNode[] = []; + + if (attributesInTwoColumns) { + for (let i = 0; i < otherAttributes.length; i += 2) { + const rightIdx = i + 1; + + rows.push( + + {getAttributeElement(otherAttributes[i])} + {rightIdx < otherAttributes.length && + getAttributeElement(otherAttributes[rightIdx])} + + ); + } + } else { + for (const attr of otherAttributes) { + rows.push(getAttributeElement(attr)); + } + } + + for (const attr of boolAttributes) { + rows.push(getAttributeElement(attr)); + } + + return rows; + }, [dealAttributes, getAttributeElement]); + + return ( + + {attributesRows} + + + Сохранить + + + + ); +}; + +export default AttributeEditor; diff --git a/src/app/deals/drawers/DealEditorDrawer/hooks/useDealAttributeValuesActions.ts b/src/components/ui/AttributesEditor/useDealAttributeValuesActions.ts similarity index 100% rename from src/app/deals/drawers/DealEditorDrawer/hooks/useDealAttributeValuesActions.ts rename to src/components/ui/AttributesEditor/useDealAttributeValuesActions.ts diff --git a/src/modules/attributes.tsx b/src/modules/attributes.tsx new file mode 100644 index 0000000..786c299 --- /dev/null +++ b/src/modules/attributes.tsx @@ -0,0 +1,5 @@ +enum Attributes { + WAREHOUSE_SELECT = 1, +} + +export default Attributes; diff --git a/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/DealInfoView.tsx b/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/DealInfoView.tsx index dbf859b..7d51e8c 100644 --- a/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/DealInfoView.tsx +++ b/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/DealInfoView.tsx @@ -2,12 +2,19 @@ import { Flex, Stack } from "@mantine/core"; import ProductsActions from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/components/ProductsActions/ProductsActions"; import TotalPriceLabel from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealInfoView/components/TotalPriceLabel/TotalPriceLabel"; import DealServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/DealServicesTable/DealServicesTable"; +import FulfillmentAttributesEditor from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/FulfillmentAttributesEditor/FulfillmentAttributesEditor"; import styles from "@/modules/dealModularEditorTabs/FulfillmentBase/FulfillmentBase.module.css"; const DealInfoView = () => ( + + + { + h={"73vh"}> { + const { deal } = useFulfillmentBaseContext(); + + return ( + + ); +}; + +export default FulfillmentAttributesEditor; diff --git a/src/modules/modules.tsx b/src/modules/modules.tsx index e5c3f2f..700fb68 100644 --- a/src/modules/modules.tsx +++ b/src/modules/modules.tsx @@ -19,6 +19,7 @@ export enum ModuleNames { const MODULES: ModulesType = { [ModuleNames.FULFILLMENT_BASE]: { info: { + id: 1, key: "fulfillment_base", label: "Фулфиллмент", }, @@ -48,12 +49,13 @@ const MODULES: ModulesType = { }, [ModuleNames.CLIENTS]: { info: { + id: 2, key: "clients", label: "Клиенты", }, tabs: [ { - label: "Клиенты", + label: "Клиент", key: "clients", icon: , device: "both", diff --git a/src/modules/modulesFileGen/modulesFileGen.ts b/src/modules/modulesFileGen/modulesFileGen.ts index de436a3..d7d3e25 100644 --- a/src/modules/modulesFileGen/modulesFileGen.ts +++ b/src/modules/modulesFileGen/modulesFileGen.ts @@ -50,7 +50,7 @@ const kwargs = getArgs(); // region constants const HOST = kwargs.host ?? kwargs.h ?? "127.0.0.1"; const PORT = kwargs.port ?? kwargs.p ?? "8000"; -const ENDPOINT = `http://${HOST}:${PORT}/api/module/built-in/`; +const ENDPOINT = `http://${HOST}:${PORT}/api/crm/v1/module/`; const TEMPLATE_PATH = path.join( __dirname, diff --git a/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs b/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs index e681249..f75b22a 100644 --- a/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs +++ b/src/modules/modulesFileGen/templates/modulesFileTemplate.hbs @@ -22,6 +22,7 @@ const MODULES: ModulesType = { {{#each modules}} [ModuleNames.{{uppercase this.key}}]: { info: { + id: {{this.id}}, key: "{{this.key}}", label: "{{this.label}}", }, diff --git a/src/modules/types.tsx b/src/modules/types.tsx index 3709c1f..9577ed7 100644 --- a/src/modules/types.tsx +++ b/src/modules/types.tsx @@ -12,6 +12,7 @@ export type ModuleTab = { export type Module = { info: { + id: number; label: string; key: string; };