refactor: refactored product services table
This commit is contained in:
@ -1,12 +1,11 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { IconCopy, IconMoodSad } from "@tabler/icons-react";
|
import { IconCopy, IconMoodSad } from "@tabler/icons-react";
|
||||||
import { Button, Flex, Group, Stack, Text } from "@mantine/core";
|
import { Button, Flex, Group, Stack, Text } from "@mantine/core";
|
||||||
import { modals } from "@mantine/modals";
|
|
||||||
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
|
||||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||||
import { DealProductSchema, ProductServiceSchema } from "@/lib/client";
|
import { DealProductSchema } from "@/lib/client";
|
||||||
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductView/hooks/useProductServicesTableColumns";
|
import useProductServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/utils/useProductServicesTable";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/utils/useProductServicesTableColumns";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealProduct: DealProductSchema;
|
dealProduct: DealProductSchema;
|
||||||
@ -19,64 +18,23 @@ const ProductServicesTable: FC<Props> = ({
|
|||||||
onDuplicateServices,
|
onDuplicateServices,
|
||||||
onKitAdd,
|
onKitAdd,
|
||||||
}) => {
|
}) => {
|
||||||
const { productServiceCrud, dealProductsList } =
|
const {
|
||||||
useFulfillmentBaseContext();
|
onChange,
|
||||||
|
onCreate,
|
||||||
const onChange = (item: ProductServiceSchema) => {
|
onDelete,
|
||||||
const excludeServiceIds = dealProduct.productServices.map(
|
isEmptyTable,
|
||||||
productService => productService.service.id
|
isDuplicateServicesDisabled,
|
||||||
);
|
} = useProductServicesTable({
|
||||||
const totalQuantity = dealProductsList.dealProducts.reduce(
|
dealProduct,
|
||||||
(sum, prod) => prod.quantity + sum,
|
});
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
modals.openContextModal({
|
|
||||||
modal: "productServiceEditorModal",
|
|
||||||
innerProps: {
|
|
||||||
entity: item,
|
|
||||||
onChange: values =>
|
|
||||||
productServiceCrud.onUpdate(
|
|
||||||
item.dealId,
|
|
||||||
item.productId,
|
|
||||||
item.serviceId,
|
|
||||||
values
|
|
||||||
),
|
|
||||||
excludeServiceIds,
|
|
||||||
quantity: totalQuantity,
|
|
||||||
isEditing: true,
|
|
||||||
},
|
|
||||||
withCloseButton: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = useProductServicesTableColumns({
|
const columns = useProductServicesTableColumns({
|
||||||
data: dealProduct.productServices,
|
data: dealProduct.productServices,
|
||||||
quantity: dealProduct.quantity,
|
quantity: dealProduct.quantity,
|
||||||
onDelete: productServiceCrud.onDelete,
|
onDelete,
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCreateClick = () => {
|
|
||||||
const excludeServiceIds = dealProduct.productServices.map(
|
|
||||||
productService => productService.service.id
|
|
||||||
);
|
|
||||||
|
|
||||||
modals.openContextModal({
|
|
||||||
modal: "productServiceEditorModal",
|
|
||||||
innerProps: {
|
|
||||||
onCreate: values =>
|
|
||||||
productServiceCrud.onCreate({ ...dealProduct, ...values }),
|
|
||||||
excludeServiceIds,
|
|
||||||
quantity: dealProduct.quantity,
|
|
||||||
isEditing: false,
|
|
||||||
},
|
|
||||||
withCloseButton: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const isEmptyTable = dealProduct.productServices.length === 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<BaseTable
|
<BaseTable
|
||||||
@ -104,7 +62,7 @@ const ProductServicesTable: FC<Props> = ({
|
|||||||
{onDuplicateServices && (
|
{onDuplicateServices && (
|
||||||
<ActionIconWithTip
|
<ActionIconWithTip
|
||||||
tipLabel={"Продублировать услуги"}
|
tipLabel={"Продублировать услуги"}
|
||||||
disabled={dealProductsList.dealProducts.length <= 1}
|
disabled={isDuplicateServicesDisabled}
|
||||||
onClick={onDuplicateServices}>
|
onClick={onDuplicateServices}>
|
||||||
<IconCopy />
|
<IconCopy />
|
||||||
</ActionIconWithTip>
|
</ActionIconWithTip>
|
||||||
@ -117,7 +75,7 @@ const ProductServicesTable: FC<Props> = ({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
onClick={onCreateClick}
|
onClick={onCreate}
|
||||||
variant={"default"}>
|
variant={"default"}>
|
||||||
Добавить услугу
|
Добавить услугу
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,75 +1,26 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { IconMoodSad } from "@tabler/icons-react";
|
import { IconMoodSad } from "@tabler/icons-react";
|
||||||
import { Button, Flex, Group, ScrollArea, Text } from "@mantine/core";
|
import { Button, Flex, Group, ScrollArea, Text } from "@mantine/core";
|
||||||
import { modals } from "@mantine/modals";
|
|
||||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||||
import { DealProductSchema, ProductServiceSchema } from "@/lib/client";
|
import { DealProductSchema } from "@/lib/client";
|
||||||
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/mobile/components/ProductServicesTable/useProductServicesTableColumns";
|
import useProductServicesTable from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/utils/useProductServicesTable";
|
||||||
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
import useProductServicesTableColumns from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/utils/useProductServicesTableColumns";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
dealProduct: DealProductSchema;
|
dealProduct: DealProductSchema;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProductServicesTable: FC<Props> = ({ dealProduct }) => {
|
const ProductServicesTable: FC<Props> = ({ dealProduct }) => {
|
||||||
const { productServiceCrud, dealProductsList } =
|
const { onChange, onCreate, onDelete, isEmptyTable } =
|
||||||
useFulfillmentBaseContext();
|
useProductServicesTable({ dealProduct });
|
||||||
|
|
||||||
const onChange = (item: ProductServiceSchema) => {
|
|
||||||
const excludeServiceIds = dealProduct.productServices.map(
|
|
||||||
productService => productService.service.id
|
|
||||||
);
|
|
||||||
const totalQuantity = dealProductsList.dealProducts.reduce(
|
|
||||||
(sum, prod) => prod.quantity + sum,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
modals.openContextModal({
|
|
||||||
modal: "productServiceEditorModal",
|
|
||||||
innerProps: {
|
|
||||||
entity: item,
|
|
||||||
onChange: values =>
|
|
||||||
productServiceCrud.onUpdate(
|
|
||||||
item.dealId,
|
|
||||||
item.productId,
|
|
||||||
item.serviceId,
|
|
||||||
values
|
|
||||||
),
|
|
||||||
excludeServiceIds,
|
|
||||||
quantity: totalQuantity,
|
|
||||||
isEditing: true,
|
|
||||||
},
|
|
||||||
withCloseButton: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = useProductServicesTableColumns({
|
const columns = useProductServicesTableColumns({
|
||||||
data: dealProduct.productServices,
|
data: dealProduct.productServices,
|
||||||
quantity: dealProduct.quantity,
|
quantity: dealProduct.quantity,
|
||||||
onDelete: productServiceCrud.onDelete,
|
onDelete,
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCreateClick = () => {
|
|
||||||
const excludeServiceIds = dealProduct.productServices.map(
|
|
||||||
productService => productService.service.id
|
|
||||||
);
|
|
||||||
|
|
||||||
modals.openContextModal({
|
|
||||||
modal: "productServiceEditorModal",
|
|
||||||
innerProps: {
|
|
||||||
onCreate: values =>
|
|
||||||
productServiceCrud.onCreate({ ...dealProduct, ...values }),
|
|
||||||
excludeServiceIds,
|
|
||||||
quantity: dealProduct.quantity,
|
|
||||||
isEditing: false,
|
|
||||||
},
|
|
||||||
withCloseButton: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const isEmptyTable = dealProduct.productServices.length === 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
flex={1}
|
flex={1}
|
||||||
@ -105,7 +56,7 @@ const ProductServicesTable: FC<Props> = ({ dealProduct }) => {
|
|||||||
<Button
|
<Button
|
||||||
flex={1}
|
flex={1}
|
||||||
py={"xs"}
|
py={"xs"}
|
||||||
onClick={onCreateClick}
|
onClick={onCreate}
|
||||||
variant={"default"}>
|
variant={"default"}>
|
||||||
Добавить услугу
|
Добавить услугу
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,62 +0,0 @@
|
|||||||
import { useMemo } from "react";
|
|
||||||
import { DataTableColumn } from "mantine-datatable";
|
|
||||||
import { Text } from "@mantine/core";
|
|
||||||
import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions";
|
|
||||||
import { ProductServiceSchema } from "@/lib/client";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
data: ProductServiceSchema[];
|
|
||||||
quantity: number;
|
|
||||||
onChange: (dealProductService: ProductServiceSchema) => void;
|
|
||||||
onDelete: (dealProductService: ProductServiceSchema) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useProductServicesTableColumns = ({
|
|
||||||
data,
|
|
||||||
quantity,
|
|
||||||
onChange,
|
|
||||||
onDelete,
|
|
||||||
}: Props) => {
|
|
||||||
const totalPrice = useMemo(
|
|
||||||
() => data.reduce((acc, row) => acc + row.price * quantity, 0),
|
|
||||||
[data, quantity]
|
|
||||||
);
|
|
||||||
|
|
||||||
return useMemo(
|
|
||||||
() =>
|
|
||||||
[
|
|
||||||
{
|
|
||||||
accessor: "actions",
|
|
||||||
title: "Действия",
|
|
||||||
textAlign: "center",
|
|
||||||
width: "0%",
|
|
||||||
render: dealProductService => (
|
|
||||||
<UpdateDeleteTableActions
|
|
||||||
onDelete={() => onDelete(dealProductService)}
|
|
||||||
onChange={() => onChange(dealProductService)}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessor: "service.name",
|
|
||||||
title: "Услуга",
|
|
||||||
width: "70%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessor: "price",
|
|
||||||
title: "Цена",
|
|
||||||
width: "30%",
|
|
||||||
render: productService =>
|
|
||||||
productService.price.toLocaleString("ru"),
|
|
||||||
footer: data.length > 0 && (
|
|
||||||
<Text fw={700}>
|
|
||||||
Итог: {totalPrice.toLocaleString("ru")}₽
|
|
||||||
</Text>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
] as DataTableColumn<ProductServiceSchema>[],
|
|
||||||
[totalPrice]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useProductServicesTableColumns;
|
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import { DealProductSchema, ProductServiceSchema } from "@/lib/client";
|
||||||
|
import { useFulfillmentBaseContext } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/contexts/FulfillmentBaseContext";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
dealProduct: DealProductSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useProductServicesTable = ({ dealProduct }: Props) => {
|
||||||
|
const { productServiceCrud, dealProductsList } =
|
||||||
|
useFulfillmentBaseContext();
|
||||||
|
|
||||||
|
const onChange = (item: ProductServiceSchema) => {
|
||||||
|
const excludeServiceIds = dealProduct.productServices.map(
|
||||||
|
productService => productService.service.id
|
||||||
|
);
|
||||||
|
const totalQuantity = dealProductsList.dealProducts.reduce(
|
||||||
|
(sum, prod) => prod.quantity + sum,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
modals.openContextModal({
|
||||||
|
modal: "productServiceEditorModal",
|
||||||
|
innerProps: {
|
||||||
|
entity: item,
|
||||||
|
onChange: values =>
|
||||||
|
productServiceCrud.onUpdate(
|
||||||
|
item.dealId,
|
||||||
|
item.productId,
|
||||||
|
item.serviceId,
|
||||||
|
values
|
||||||
|
),
|
||||||
|
excludeServiceIds,
|
||||||
|
quantity: totalQuantity,
|
||||||
|
isEditing: true,
|
||||||
|
},
|
||||||
|
withCloseButton: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreate = () => {
|
||||||
|
const excludeServiceIds = dealProduct.productServices.map(
|
||||||
|
productService => productService.service.id
|
||||||
|
);
|
||||||
|
|
||||||
|
modals.openContextModal({
|
||||||
|
modal: "productServiceEditorModal",
|
||||||
|
innerProps: {
|
||||||
|
onCreate: values =>
|
||||||
|
productServiceCrud.onCreate({ ...dealProduct, ...values }),
|
||||||
|
excludeServiceIds,
|
||||||
|
quantity: dealProduct.quantity,
|
||||||
|
isEditing: false,
|
||||||
|
},
|
||||||
|
withCloseButton: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = productServiceCrud.onDelete;
|
||||||
|
|
||||||
|
const isEmptyTable = dealProduct.productServices.length === 0;
|
||||||
|
const isDuplicateServicesDisabled =
|
||||||
|
dealProductsList.dealProducts.length <= 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
onChange,
|
||||||
|
onCreate,
|
||||||
|
onDelete,
|
||||||
|
isEmptyTable,
|
||||||
|
isDuplicateServicesDisabled,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useProductServicesTable;
|
||||||
@ -2,6 +2,7 @@ import { useMemo } from "react";
|
|||||||
import { DataTableColumn } from "mantine-datatable";
|
import { DataTableColumn } from "mantine-datatable";
|
||||||
import { Box, Text } from "@mantine/core";
|
import { Box, Text } from "@mantine/core";
|
||||||
import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions";
|
import UpdateDeleteTableActions from "@/components/ui/BaseTable/components/UpdateDeleteTableActions";
|
||||||
|
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||||
import { ProductServiceSchema } from "@/lib/client";
|
import { ProductServiceSchema } from "@/lib/client";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -17,6 +18,8 @@ const useProductServicesTableColumns = ({
|
|||||||
onChange,
|
onChange,
|
||||||
onDelete,
|
onDelete,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
const totalPrice = useMemo(
|
const totalPrice = useMemo(
|
||||||
() => data.reduce((acc, row) => acc + row.price * quantity, 0),
|
() => data.reduce((acc, row) => acc + row.price * quantity, 0),
|
||||||
[data, quantity]
|
[data, quantity]
|
||||||
@ -34,21 +37,27 @@ const useProductServicesTableColumns = ({
|
|||||||
<UpdateDeleteTableActions
|
<UpdateDeleteTableActions
|
||||||
onDelete={() => onDelete(dealProductService)}
|
onDelete={() => onDelete(dealProductService)}
|
||||||
onChange={() => onChange(dealProductService)}
|
onChange={() => onChange(dealProductService)}
|
||||||
style={{ padding: "var(--mantine-spacing-xs)" }}
|
style={{
|
||||||
|
padding: isMobile
|
||||||
|
? 0
|
||||||
|
: "var(--mantine-spacing-xs)",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: "service.name",
|
accessor: "service.name",
|
||||||
title: "Услуга",
|
title: "Услуга",
|
||||||
|
width: "70%",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: "price",
|
accessor: "price",
|
||||||
title: "Цена",
|
title: "Цена",
|
||||||
|
width: "30%",
|
||||||
render: productService =>
|
render: productService =>
|
||||||
productService.price.toLocaleString("ru"),
|
productService.price.toLocaleString("ru"),
|
||||||
footer: data.length > 0 && (
|
footer: data.length > 0 && (
|
||||||
<Box my={"sm"}>
|
<Box my={isMobile ? 0 : "sm"}>
|
||||||
<Text fw={700}>
|
<Text fw={700}>
|
||||||
Итог: {totalPrice.toLocaleString("ru")}₽
|
Итог: {totalPrice.toLocaleString("ru")}₽
|
||||||
</Text>
|
</Text>
|
||||||
@ -56,7 +65,7 @@ const useProductServicesTableColumns = ({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
] as DataTableColumn<ProductServiceSchema>[],
|
] as DataTableColumn<ProductServiceSchema>[],
|
||||||
[totalPrice]
|
[totalPrice, isMobile]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user