From cc910c849548b2ee83f37bf21d53880a054938d4 Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Thu, 6 Nov 2025 12:09:27 +0400 Subject: [PATCH] feat: modules page and module editor page for mobiles --- .../actions/components/PageBody/PageBody.tsx | 7 +- src/app/actions/data/mobileButtonsData.tsx | 2 +- .../AttributeSelect/AttributeSelect.tsx | 40 ++++++++ .../useAttributesTableColumns.tsx | 2 +- .../ModuleAttribute/ModuleAttribute.tsx | 2 +- .../ModuleAttributesEditor.tsx | 28 +++++- .../ModuleCommonInfoEditor.tsx | 3 + .../components/shared/PageBody/PageBody.tsx | 95 ++++++++++++------- .../[moduleId]/hooks/useAttributesActions.tsx | 11 ++- .../[moduleId]/hooks/useAttributesCrud.tsx | 7 +- .../[moduleId]/modals/AddAttributeModal.tsx | 51 ++++++++++ .../hooks/useAttributesInnerTableColumns.tsx | 5 +- .../modules/hooks/useModulesTableColumns.tsx | 2 + src/modals/modals.ts | 2 + 14 files changed, 210 insertions(+), 47 deletions(-) create mode 100644 src/app/module-editor/[moduleId]/components/mobile/AttributeSelect/AttributeSelect.tsx create mode 100644 src/app/module-editor/[moduleId]/modals/AddAttributeModal.tsx diff --git a/src/app/actions/components/PageBody/PageBody.tsx b/src/app/actions/components/PageBody/PageBody.tsx index 33376f7..abe99d2 100644 --- a/src/app/actions/components/PageBody/PageBody.tsx +++ b/src/app/actions/components/PageBody/PageBody.tsx @@ -1,7 +1,7 @@ "use client"; import { RefObject, useMemo, useRef } from "react"; -import { IconList, IconTag } from "@tabler/icons-react"; +import { IconApps, IconList, IconTag } from "@tabler/icons-react"; import { SimpleGrid, Stack } from "@mantine/core"; import Action from "@/app/actions/components/Action/Action"; import mobileButtonsData from "@/app/actions/data/mobileButtonsData"; @@ -28,6 +28,11 @@ const PageBody = () => { label: "Атрибуты", href: "/attributes", }, + { + icon: IconApps, + label: "Модули", + href: "/modules", + }, { icon: IconTag, label: "Теги", diff --git a/src/app/actions/data/mobileButtonsData.tsx b/src/app/actions/data/mobileButtonsData.tsx index a09b95e..d536324 100644 --- a/src/app/actions/data/mobileButtonsData.tsx +++ b/src/app/actions/data/mobileButtonsData.tsx @@ -28,7 +28,7 @@ const mobileButtonsData: LinkData[] = [ }, { icon: IconFileBarcode, - label: "Шаблоны штрихкодов", + label: "Шаблоны ШК", href: "/barcode-templates", moduleName: ModuleNames.FULFILLMENT_BASE, }, diff --git a/src/app/module-editor/[moduleId]/components/mobile/AttributeSelect/AttributeSelect.tsx b/src/app/module-editor/[moduleId]/components/mobile/AttributeSelect/AttributeSelect.tsx new file mode 100644 index 0000000..8a11e50 --- /dev/null +++ b/src/app/module-editor/[moduleId]/components/mobile/AttributeSelect/AttributeSelect.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { FC, useMemo } from "react"; +import useAttributesList from "@/app/module-editor/[moduleId]/hooks/useAttributesList"; +import ObjectSelect, { + ObjectSelectProps, +} from "@/components/selects/ObjectSelect/ObjectSelect"; +import { AttributeSchema } from "@/lib/client"; + +type Props = Omit< + ObjectSelectProps, + "data" | "getLabelFn" | "getValueFn" +> & { + attributesToExclude?: AttributeSchema[]; +}; + +const AttributeSelect: FC = ({ attributesToExclude, ...props }) => { + const { attributes } = useAttributesList(); + + const availableAttributes = useMemo(() => { + const attrIdsToExcludeSet = new Set( + attributesToExclude?.map(a => a.id) + ); + + return attributes.filter(a => !attrIdsToExcludeSet.has(a.id)); + }, [attributes, attributesToExclude]); + + return ( + props.onChange(null)} + getLabelFn={(option: AttributeSchema) => option.label} + data={availableAttributes} + {...props} + /> + ); +}; + +export default AttributeSelect; diff --git a/src/app/module-editor/[moduleId]/components/shared/AttributesTable/useAttributesTableColumns.tsx b/src/app/module-editor/[moduleId]/components/shared/AttributesTable/useAttributesTableColumns.tsx index fa4b5f0..6e10232 100644 --- a/src/app/module-editor/[moduleId]/components/shared/AttributesTable/useAttributesTableColumns.tsx +++ b/src/app/module-editor/[moduleId]/components/shared/AttributesTable/useAttributesTableColumns.tsx @@ -24,7 +24,7 @@ const useAttributesTableColumns = () => { accessor: "type.name", render: attr => attr.type.type === "select" - ? `Выбор "${attr.select?.label}"` + ? `Выбор "${attr.select?.name}"` : attr.type.name, }, { diff --git a/src/app/module-editor/[moduleId]/components/shared/ModuleAttribute/ModuleAttribute.tsx b/src/app/module-editor/[moduleId]/components/shared/ModuleAttribute/ModuleAttribute.tsx index ab11d25..738921f 100644 --- a/src/app/module-editor/[moduleId]/components/shared/ModuleAttribute/ModuleAttribute.tsx +++ b/src/app/module-editor/[moduleId]/components/shared/ModuleAttribute/ModuleAttribute.tsx @@ -42,7 +42,7 @@ const ModuleAttribute: FC = ({ attribute }) => { <>{getAttrLabelText()} Тип: {attribute.type.name}{" "} - {attribute.select && `"${attribute.select.label}"`} + {attribute.select && `"${attribute.select.name}"`} { - const { module } = useModuleEditorContext(); + const { + module, + attributeActions: { addAttributeToModule }, + } = useModuleEditorContext(); + const isMobile = useIsMobile(); const getAttributesRows = () => { if (!module?.attributes) return []; @@ -29,10 +36,27 @@ const ModuleAttributesEditor = () => { return rows; }; + const onAddAttributeClick = () => { + modals.openContextModal({ + modal: "addAttributeModal", + title: "Добавление атрибута", + withCloseButton: true, + innerProps: { + onSubmit: addAttributeToModule, + usedAttributes: module?.attributes ?? [], + }, + }); + }; + return ( + {isMobile && ( + + Добавить атрибут + + )} {getAttributesRows()} ); diff --git a/src/app/module-editor/[moduleId]/components/shared/ModuleCommonInfoEditor/ModuleCommonInfoEditor.tsx b/src/app/module-editor/[moduleId]/components/shared/ModuleCommonInfoEditor/ModuleCommonInfoEditor.tsx index 0ddff1d..e6355f0 100644 --- a/src/app/module-editor/[moduleId]/components/shared/ModuleCommonInfoEditor/ModuleCommonInfoEditor.tsx +++ b/src/app/module-editor/[moduleId]/components/shared/ModuleCommonInfoEditor/ModuleCommonInfoEditor.tsx @@ -1,6 +1,7 @@ import { Button, Flex, Group, Textarea, TextInput } from "@mantine/core"; import { useForm } from "@mantine/form"; import { useModuleEditorContext } from "@/app/module-editor/[moduleId]/contexts/ModuleEditorContext"; +import useIsMobile from "@/hooks/utils/useIsMobile"; import { ModuleInfo } from "../../../hooks/useModulesActions"; const ModuleCommonInfoEditor = () => { @@ -8,6 +9,7 @@ const ModuleCommonInfoEditor = () => { module, moduleActions: { updateCommonInfo }, } = useModuleEditorContext(); + const isMobile = useIsMobile(); const form = useForm({ initialValues: module ?? { @@ -39,6 +41,7 @@ const ModuleCommonInfoEditor = () => { + + + ); +}; + +export default AddAttributeModal; diff --git a/src/app/modules/hooks/useAttributesInnerTableColumns.tsx b/src/app/modules/hooks/useAttributesInnerTableColumns.tsx index 25675f4..7c47834 100644 --- a/src/app/modules/hooks/useAttributesInnerTableColumns.tsx +++ b/src/app/modules/hooks/useAttributesInnerTableColumns.tsx @@ -25,23 +25,26 @@ const useAttributesInnerTableColumns = () => { accessor: "type.name", render: attr => attr.type.type === "select" - ? `Выбор "${attr.select?.label}"` + ? `Выбор "${attr.select?.name}"` : attr.type.name, }, { title: "Значение по умолчанию", accessor: "defaultValue", render: attr => , + hidden: isMobile, }, { title: "Синхронизировано в группе", accessor: "isApplicableToGroup", render: attr => renderCheck(attr.isApplicableToGroup), + hidden: isMobile, }, { title: "Может быть пустым", accessor: "isNullable", render: attr => renderCheck(attr.isNullable), + hidden: isMobile, }, { title: "Описаниие", diff --git a/src/app/modules/hooks/useModulesTableColumns.tsx b/src/app/modules/hooks/useModulesTableColumns.tsx index 0e79891..78ebab9 100644 --- a/src/app/modules/hooks/useModulesTableColumns.tsx +++ b/src/app/modules/hooks/useModulesTableColumns.tsx @@ -74,6 +74,7 @@ const useModulesTableColumns = ({ { title: "Описание", accessor: "description", + hidden: isMobile, }, { title: "Зависит от модулей", @@ -83,6 +84,7 @@ const useModulesTableColumns = ({ {module.dependsOn?.map(m => m.label).join(", ")} ), + hidden: isMobile, }, { accessor: "actions", diff --git a/src/modals/modals.ts b/src/modals/modals.ts index 1a19442..29852f1 100644 --- a/src/modals/modals.ts +++ b/src/modals/modals.ts @@ -5,6 +5,7 @@ import ColorPickerModal from "@/app/deals/modals/ColorPickerModal/ColorPickerMod import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/DealsBoardFiltersModal"; import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal"; import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal"; +import AddAttributeModal from "@/app/module-editor/[moduleId]/modals/AddAttributeModal"; import AttributeEditorModal from "@/app/module-editor/[moduleId]/modals/AttributeEditorModal"; import ModuleCreatorModal from "@/app/modules/modals/ModuleCreatorModal"; import { @@ -46,4 +47,5 @@ export const modals = { dealTagModal: DealTagModal, attributeEditorModal: AttributeEditorModal, moduleCreatorModal: ModuleCreatorModal, + addAttributeModal: AddAttributeModal, };