From 61f0a9069b75ed2eb6ddc6e9f5081f45a5fb6bec Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Sun, 28 Sep 2025 12:46:57 +0400 Subject: [PATCH] feat: actions for services and categories --- .../components/shared/PageBody/PageBody.tsx | 4 +- .../hooks/useServicesKitsTableColumns.tsx | 24 ++---- .../shared/ServicesTable/ServicesTable.tsx | 8 ++ .../hooks/servicesInnerTableColumns.tsx | 28 ++++++- .../hooks/servicesOuterTableColumns.tsx | 26 ++++-- src/app/services/contexts/ServicesContext.tsx | 15 ++-- .../components/RangePriceInput.tsx | 9 +- .../components/UpdateDeleteTableActions.tsx | 84 +++++++++++++++++++ .../hooks/useProductServicesTableColumns.tsx | 25 ++---- .../useDealServicesTableColumns.tsx | 20 ++--- .../useProductServicesTableColumns.tsx | 21 ++--- .../hooks/cruds/useServiceCategoriesCrud.tsx | 2 +- 12 files changed, 178 insertions(+), 88 deletions(-) create mode 100644 src/components/ui/BaseTable/components/UpdateDeleteTableActions.tsx diff --git a/src/app/services/components/shared/PageBody/PageBody.tsx b/src/app/services/components/shared/PageBody/PageBody.tsx index 3a7b6ad..5e407ac 100644 --- a/src/app/services/components/shared/PageBody/PageBody.tsx +++ b/src/app/services/components/shared/PageBody/PageBody.tsx @@ -43,7 +43,9 @@ const PageBody = () => { /> )} - +
{ - const isMobile = useIsMobile(); - return useMemo( () => [ @@ -25,19 +20,10 @@ const useServicesKitsTableColumns = ({ onDelete, onChange }: Props) => { textAlign: "center", width: "0%", render: kit => ( - - onChange(kit)} - tipLabel={"Редактировать"}> - - - onDelete(kit)} - tipLabel={"Удалить"}> - - - + onDelete(kit)} + onChange={() => onChange(kit)} + /> ), }, { diff --git a/src/app/services/components/shared/ServicesTable/ServicesTable.tsx b/src/app/services/components/shared/ServicesTable/ServicesTable.tsx index 2938e76..396db42 100644 --- a/src/app/services/components/shared/ServicesTable/ServicesTable.tsx +++ b/src/app/services/components/shared/ServicesTable/ServicesTable.tsx @@ -6,6 +6,7 @@ import useServicesOuterTableColumns from "@/app/services/components/shared/Servi import { GroupedServices } from "@/app/services/components/shared/ServicesTable/types/GroupedServices"; import { useServicesContext } from "@/app/services/contexts/ServicesContext"; import BaseTable from "@/components/ui/BaseTable/BaseTable"; +import useIsMobile from "@/hooks/utils/useIsMobile"; import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service"; type Props = { @@ -14,6 +15,7 @@ type Props = { const ServicesTable: FC = ({ serviceType }) => { const { servicesList } = useServicesContext(); + const isMobile = useIsMobile(); const [expandedCategoryIds, setExpandedCategoryIds] = useState( [] @@ -53,6 +55,9 @@ const ServicesTable: FC = ({ serviceType }) => { verticalSpacing={"md"} groups={undefined} idAccessor={"category.id"} + styles={{ + header: { zIndex: 1000 }, + }} rowExpansion={{ allowMultiple: true, expanded: { @@ -69,6 +74,9 @@ const ServicesTable: FC = ({ serviceType }) => { /> ), }} + style={{ + marginInline: isMobile ? "var(--mantine-spacing-xs)" : "0", + }} /> ); }; diff --git a/src/app/services/components/shared/ServicesTable/hooks/servicesInnerTableColumns.tsx b/src/app/services/components/shared/ServicesTable/hooks/servicesInnerTableColumns.tsx index 8d74e29..bfbe09b 100644 --- a/src/app/services/components/shared/ServicesTable/hooks/servicesInnerTableColumns.tsx +++ b/src/app/services/components/shared/ServicesTable/hooks/servicesInnerTableColumns.tsx @@ -1,9 +1,19 @@ +"use client"; + import { useMemo } from "react"; import { DataTableColumn } from "mantine-datatable"; import { List, Text } from "@mantine/core"; +import { useServicesContext } from "@/app/services/contexts/ServicesContext"; +import useServicesActions from "@/app/services/hooks/useServicesActions"; +import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions"; +import useIsMobile from "@/hooks/utils/useIsMobile"; import { ServiceSchema } from "@/lib/client"; const useServicesInnerTableColumns = () => { + const { onChangeService } = useServicesActions(); + const { servicesCrud } = useServicesContext(); + const isMobile = useIsMobile(); + const getPriceRow = (service: ServiceSchema) => { if (service.priceRanges.length === 0) { return <>{service.price.toLocaleString("ru")}₽; @@ -35,11 +45,25 @@ const useServicesInnerTableColumns = () => { }, { accessor: "cost", - title: "Себестоимость", + title: isMobile ? "Себестоим." : "Себестоимость", render: service => `${service.cost?.toLocaleString("ru")}₽`, }, + { + accessor: "actions", + title: isMobile ? "" : "Действия", + sortable: false, + textAlign: "center", + width: "0%", + render: service => ( + servicesCrud.onDelete(service)} + onChange={() => onChangeService(service)} + dotsForMobile + /> + ), + }, ] as DataTableColumn[], - [] + [isMobile] ); }; diff --git a/src/app/services/components/shared/ServicesTable/hooks/servicesOuterTableColumns.tsx b/src/app/services/components/shared/ServicesTable/hooks/servicesOuterTableColumns.tsx index 286d5d2..1db4d32 100644 --- a/src/app/services/components/shared/ServicesTable/hooks/servicesOuterTableColumns.tsx +++ b/src/app/services/components/shared/ServicesTable/hooks/servicesOuterTableColumns.tsx @@ -10,6 +10,8 @@ import { DataTableColumn } from "mantine-datatable"; import { Box, Group, Text } from "@mantine/core"; import { GroupedServices } from "@/app/services/components/shared/ServicesTable/types/GroupedServices"; import { useServicesContext } from "@/app/services/contexts/ServicesContext"; +import useCategoriesActions from "@/app/services/hooks/useCategoriesActions"; +import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions"; type Props = { expandedCategoryIds: number[]; @@ -20,18 +22,19 @@ const useServicesOuterTableColumns = ({ expandedCategoryIds, setExpandedCategoryIds, }: Props) => { - const { categoriesList } = useServicesContext(); + const { onChangeCategory } = useCategoriesActions(); + const { categoriesCrud, categories } = useServicesContext(); const onExpandAllClick = () => { - if (expandedCategoryIds.length !== categoriesList.categories.length) { - setExpandedCategoryIds(categoriesList.categories.map(c => c.id)); + if (expandedCategoryIds.length !== categories.length) { + setExpandedCategoryIds(categories.map(c => c.id)); return; } setExpandedCategoryIds([]); }; const getExpandAllIcon = () => { - if (expandedCategoryIds.length === categoriesList.categories.length) + if (expandedCategoryIds.length === categories.length) return ; if (expandedCategoryIds.length === 0) return ; return ; @@ -64,8 +67,21 @@ const useServicesOuterTableColumns = ({ ), }, + { + accessor: "actions", + title: "Действия", + sortable: false, + textAlign: "center", + width: "0%", + render: ({ category }) => ( + categoriesCrud.onDelete(category)} + onChange={() => onChangeCategory(category)} + /> + ), + }, ] as DataTableColumn[], - [expandedCategoryIds, categoriesList.categories] + [expandedCategoryIds, categories] ); }; diff --git a/src/app/services/contexts/ServicesContext.tsx b/src/app/services/contexts/ServicesContext.tsx index 0d6a6d1..c05c37a 100644 --- a/src/app/services/contexts/ServicesContext.tsx +++ b/src/app/services/contexts/ServicesContext.tsx @@ -1,5 +1,6 @@ "use client"; +import { ServiceCategorySchema } from "@/lib/client"; import makeContext from "@/lib/contextFactory/contextFactory"; import { ServiceCategoriesCrud, @@ -13,9 +14,6 @@ import { ServicesKitsCrud, useServicesKitsCrud, } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServicesKitsCrud"; -import useServiceCategoriesList, { - ServiceCategoriesList, -} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServiceCategoriesList"; import useServicesKitsList, { ServicesKitsList, } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesKitsList"; @@ -28,8 +26,8 @@ type ServicesContextState = { servicesCrud: ServicesCrud; servicesKitList: ServicesKitsList; servicesKitCrud: ServicesKitsCrud; - categoriesList: ServiceCategoriesList; categoriesCrud: ServiceCategoriesCrud; + categories: ServiceCategorySchema[]; }; const useFulfillmentBaseContextState = (): ServicesContextState => { @@ -39,16 +37,19 @@ const useFulfillmentBaseContextState = (): ServicesContextState => { const servicesKitList = useServicesKitsList(); const servicesKitCrud = useServicesKitsCrud(servicesKitList); - const categoriesList = useServiceCategoriesList(); - const categoriesCrud = useServiceCategoriesCrud(categoriesList); + const categories = [...new Set(servicesList.services.map(s => s.category))]; + const categoriesCrud = useServiceCategoriesCrud({ + queryKey: servicesList.queryKey, + categories, + }); return { servicesList, servicesCrud, servicesKitList, servicesKitCrud, - categoriesList, categoriesCrud, + categories, }; }; diff --git a/src/app/services/modals/ServiceEditorModal/components/RangePriceInput.tsx b/src/app/services/modals/ServiceEditorModal/components/RangePriceInput.tsx index 8bd47b8..2dc81c4 100644 --- a/src/app/services/modals/ServiceEditorModal/components/RangePriceInput.tsx +++ b/src/app/services/modals/ServiceEditorModal/components/RangePriceInput.tsx @@ -1,7 +1,8 @@ import { FC } from "react"; import { IconTrash } from "@tabler/icons-react"; import { isNumber } from "lodash"; -import { ActionIcon, Flex, Input, NumberInput, rem } from "@mantine/core"; +import { Flex, Input, NumberInput, rem } from "@mantine/core"; +import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip"; import InlineButton from "@/components/ui/InlineButton/InlineButton"; import { ServicePriceRangeSchema } from "@/lib/client"; import BaseFormInputProps from "@/utils/baseFormInputProps"; @@ -51,11 +52,9 @@ const RangePriceInput: FC = props => { key={idx} gap={rem(10)} align={"flex-end"}> - onDeleteRange(idx)} - variant={"default"}> + onDeleteRange(idx)}> - + void; + onDelete: () => void; + dotsForMobile?: boolean; + style?: CSSProperties; +}; + +const UpdateDeleteTableActions: FC = ({ + onChange, + onDelete, + style, + dotsForMobile = false, +}) => { + const isMobile = useIsMobile(); + + if (dotsForMobile && isMobile) { + return ( + + + e.stopPropagation()}> + + + + + + + { + e.stopPropagation(); + onChange(); + }}> + + + Редактировать + + + { + e.stopPropagation(); + onDelete(); + }}> + + + Удалить + + + + + ); + } + + return ( + + { + e.stopPropagation(); + onChange(); + }} + tipLabel={"Редактировать"}> + + + { + e.stopPropagation(); + onDelete(); + }} + tipLabel={"Удалить"}> + + + + ); +}; + +export default UpdateDeleteTableActions; diff --git a/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns.tsx b/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns.tsx index 33f2135..0b08466 100644 --- a/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns.tsx +++ b/src/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns.tsx @@ -1,8 +1,7 @@ import { useMemo } from "react"; -import { IconEdit, IconTrash } from "@tabler/icons-react"; import { DataTableColumn } from "mantine-datatable"; -import { Box, Flex, Text } from "@mantine/core"; -import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip"; +import { Box, Text } from "@mantine/core"; +import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions"; import { ProductServiceSchema } from "@/lib/client"; type Props = { @@ -32,21 +31,11 @@ const useProductServicesTableColumns = ({ textAlign: "center", width: "0%", render: dealProductService => ( - - onDelete(dealProductService)}> - - - onChange(dealProductService)}> - - - + onDelete(dealProductService)} + onChange={() => onChange(dealProductService)} + style={{ padding: "var(--mantine-spacing-xs)" }} + /> ), }, { diff --git a/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/useDealServicesTableColumns.tsx b/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/useDealServicesTableColumns.tsx index 59669e4..91dafbc 100644 --- a/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/useDealServicesTableColumns.tsx +++ b/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/DealServiceTable/useDealServicesTableColumns.tsx @@ -1,7 +1,6 @@ import { useMemo } from "react"; -import { IconEdit, IconTrash } from "@tabler/icons-react"; import { DataTableColumn } from "mantine-datatable"; -import { ActionIcon, Flex } from "@mantine/core"; +import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions"; import { DealServiceSchema } from "@/lib/client"; type Props = { @@ -36,19 +35,10 @@ const useDealServicesTableColumns = ({ onChange, onDelete }: Props) => { textAlign: "center", width: "0%", render: dealService => ( - - onDelete(dealService)}> - - - onChange(dealService)}> - - - + onDelete(dealService)} + onChange={() => onChange(dealService)} + /> ), }, ] as DataTableColumn[], diff --git a/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/ProductServicesTable/useProductServicesTableColumns.tsx b/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/ProductServicesTable/useProductServicesTableColumns.tsx index 21f4c37..fc75368 100644 --- a/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/ProductServicesTable/useProductServicesTableColumns.tsx +++ b/src/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/ProductServicesTable/useProductServicesTableColumns.tsx @@ -1,7 +1,7 @@ import { useMemo } from "react"; -import { IconEdit, IconTrash } from "@tabler/icons-react"; import { DataTableColumn } from "mantine-datatable"; -import { ActionIcon, Flex, Text } from "@mantine/core"; +import { Text } from "@mantine/core"; +import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions"; import { ProductServiceSchema } from "@/lib/client"; type Props = { @@ -31,19 +31,10 @@ const useProductServicesTableColumns = ({ textAlign: "center", width: "0%", render: dealProductService => ( - - onDelete(dealProductService)}> - - - onChange(dealProductService)}> - - - + onDelete(dealProductService)} + onChange={() => onChange(dealProductService)} + /> ), }, { diff --git a/src/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServiceCategoriesCrud.tsx b/src/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServiceCategoriesCrud.tsx index 5d2a9af..0ec1513 100644 --- a/src/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServiceCategoriesCrud.tsx +++ b/src/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServiceCategoriesCrud.tsx @@ -55,7 +55,7 @@ export const useServiceCategoriesCrud = ({ UpdateServiceCategorySchema, CreateServiceCategorySchema >({ - key: "getServiceCategories", + key: "getServices", queryKey, mutations: { create: createServiceCategoryMutation(),