feat: a few shipping products in box
This commit is contained in:
@@ -132,6 +132,8 @@ export type { CreateBoardRequest } from './models/CreateBoardRequest';
|
|||||||
export type { CreateBoardResponse } from './models/CreateBoardResponse';
|
export type { CreateBoardResponse } from './models/CreateBoardResponse';
|
||||||
export type { CreateBoxInCardSchema } from './models/CreateBoxInCardSchema';
|
export type { CreateBoxInCardSchema } from './models/CreateBoxInCardSchema';
|
||||||
export type { CreateBoxInPalletSchema } from './models/CreateBoxInPalletSchema';
|
export type { CreateBoxInPalletSchema } from './models/CreateBoxInPalletSchema';
|
||||||
|
export type { CreateBoxRequest } from './models/CreateBoxRequest';
|
||||||
|
export type { CreateBoxResponse } from './models/CreateBoxResponse';
|
||||||
export type { CreateCardBillRequest } from './models/CreateCardBillRequest';
|
export type { CreateCardBillRequest } from './models/CreateCardBillRequest';
|
||||||
export type { CreateCardBillResponse } from './models/CreateCardBillResponse';
|
export type { CreateCardBillResponse } from './models/CreateCardBillResponse';
|
||||||
export type { CreateCardGroupRequest } from './models/CreateCardGroupRequest';
|
export type { CreateCardGroupRequest } from './models/CreateCardGroupRequest';
|
||||||
@@ -354,9 +356,6 @@ export type { UpdateBoardOrderRequest } from './models/UpdateBoardOrderRequest';
|
|||||||
export type { UpdateBoardOrderResponse } from './models/UpdateBoardOrderResponse';
|
export type { UpdateBoardOrderResponse } from './models/UpdateBoardOrderResponse';
|
||||||
export type { UpdateBoardRequest } from './models/UpdateBoardRequest';
|
export type { UpdateBoardRequest } from './models/UpdateBoardRequest';
|
||||||
export type { UpdateBoardResponse } from './models/UpdateBoardResponse';
|
export type { UpdateBoardResponse } from './models/UpdateBoardResponse';
|
||||||
export type { UpdateBoxRequest } from './models/UpdateBoxRequest';
|
|
||||||
export type { UpdateBoxResponse } from './models/UpdateBoxResponse';
|
|
||||||
export type { UpdateBoxSchema } from './models/UpdateBoxSchema';
|
|
||||||
export type { UpdateDepartmentRequest } from './models/UpdateDepartmentRequest';
|
export type { UpdateDepartmentRequest } from './models/UpdateDepartmentRequest';
|
||||||
export type { UpdateDepartmentResponse } from './models/UpdateDepartmentResponse';
|
export type { UpdateDepartmentResponse } from './models/UpdateDepartmentResponse';
|
||||||
export type { UpdateDepartmentSectionRequest } from './models/UpdateDepartmentSectionRequest';
|
export type { UpdateDepartmentSectionRequest } from './models/UpdateDepartmentSectionRequest';
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import type { ProductSchema } from './ProductSchema';
|
import type { ShippingProductSchema } from './ShippingProductSchema';
|
||||||
export type BoxSchema = {
|
export type BoxSchema = {
|
||||||
id: number;
|
id: number;
|
||||||
quantity: number;
|
|
||||||
product: (ProductSchema | null);
|
|
||||||
palletId: (number | null);
|
palletId: (number | null);
|
||||||
cardId: (number | null);
|
cardId: (number | null);
|
||||||
|
shippingProducts: Array<ShippingProductSchema>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import type { CreateBoxInCardSchema } from './CreateBoxInCardSchema';
|
import type { CreateBoxInCardSchema } from './CreateBoxInCardSchema';
|
||||||
import type { CreateBoxInPalletSchema } from './CreateBoxInPalletSchema';
|
import type { CreateBoxInPalletSchema } from './CreateBoxInPalletSchema';
|
||||||
import type { UpdateBoxSchema } from './UpdateBoxSchema';
|
export type CreateBoxRequest = {
|
||||||
export type UpdateBoxRequest = {
|
data: (CreateBoxInCardSchema | CreateBoxInPalletSchema);
|
||||||
data: (CreateBoxInCardSchema | CreateBoxInPalletSchema | UpdateBoxSchema);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
export type UpdateBoxResponse = {
|
export type CreateBoxResponse = {
|
||||||
ok: boolean;
|
ok: boolean;
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
export type CreateShippingProductSchema = {
|
export type CreateShippingProductSchema = {
|
||||||
productId: (number | null);
|
productId: (number | null);
|
||||||
quantity: (number | null);
|
quantity: (number | null);
|
||||||
palletId: number;
|
palletId?: (number | null);
|
||||||
|
boxId?: (number | null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export type ShippingProductSchema = {
|
|||||||
id: number;
|
id: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
product: ProductSchema;
|
product: ProductSchema;
|
||||||
palletId: number;
|
palletId: (number | null);
|
||||||
|
boxId: (number | null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
/* generated using openapi-typescript-codegen -- do not edit */
|
|
||||||
/* istanbul ignore file */
|
|
||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
export type UpdateBoxSchema = {
|
|
||||||
productId: (number | null);
|
|
||||||
quantity: (number | null);
|
|
||||||
boxId: (number | null);
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
import type { CreateBoxRequest } from '../models/CreateBoxRequest';
|
||||||
|
import type { CreateBoxResponse } from '../models/CreateBoxResponse';
|
||||||
import type { CreatePalletResponse } from '../models/CreatePalletResponse';
|
import type { CreatePalletResponse } from '../models/CreatePalletResponse';
|
||||||
import type { DeleteBoxResponse } from '../models/DeleteBoxResponse';
|
import type { DeleteBoxResponse } from '../models/DeleteBoxResponse';
|
||||||
import type { DeletePalletResponse } from '../models/DeletePalletResponse';
|
import type { DeletePalletResponse } from '../models/DeletePalletResponse';
|
||||||
import type { DeleteShippingProductResponse } from '../models/DeleteShippingProductResponse';
|
import type { DeleteShippingProductResponse } from '../models/DeleteShippingProductResponse';
|
||||||
import type { UpdateBoxRequest } from '../models/UpdateBoxRequest';
|
|
||||||
import type { UpdateBoxResponse } from '../models/UpdateBoxResponse';
|
|
||||||
import type { UpdateShippingProductRequest } from '../models/UpdateShippingProductRequest';
|
import type { UpdateShippingProductRequest } from '../models/UpdateShippingProductRequest';
|
||||||
import type { UpdateShippingProductResponse } from '../models/UpdateShippingProductResponse';
|
import type { UpdateShippingProductResponse } from '../models/UpdateShippingProductResponse';
|
||||||
import type { CancelablePromise } from '../core/CancelablePromise';
|
import type { CancelablePromise } from '../core/CancelablePromise';
|
||||||
@@ -98,15 +98,15 @@ export class ShippingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Update Box
|
* Create Box
|
||||||
* @returns UpdateBoxResponse Successful Response
|
* @returns CreateBoxResponse Successful Response
|
||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static updateBox({
|
public static createBox({
|
||||||
requestBody,
|
requestBody,
|
||||||
}: {
|
}: {
|
||||||
requestBody: UpdateBoxRequest,
|
requestBody: CreateBoxRequest,
|
||||||
}): CancelablePromise<UpdateBoxResponse> {
|
}): CancelablePromise<CreateBoxResponse> {
|
||||||
return __request(OpenAPI, {
|
return __request(OpenAPI, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/shipping/box',
|
url: '/shipping/box',
|
||||||
|
|||||||
@@ -3,18 +3,14 @@ import { CardSchema } from "../../../client";
|
|||||||
const DATETIME_TYPES = ["datetime", "date"];
|
const DATETIME_TYPES = ["datetime", "date"];
|
||||||
|
|
||||||
const getAttributesFromCard = (card: CardSchema) => {
|
const getAttributesFromCard = (card: CardSchema) => {
|
||||||
console.log("getAttributesFromCard");
|
|
||||||
|
|
||||||
return card.attributes.reduce(
|
return card.attributes.reduce(
|
||||||
(values, cardAttribute) => {
|
(values, cardAttribute) => {
|
||||||
let value: boolean | number | string | null | Date = cardAttribute.value;
|
let value: boolean | number | string | null | Date = cardAttribute.value;
|
||||||
console.log(cardAttribute.attribute.type.type);
|
|
||||||
if (DATETIME_TYPES.includes(cardAttribute.attribute.type.type) && value !== null) {
|
if (DATETIME_TYPES.includes(cardAttribute.attribute.type.type) && value !== null) {
|
||||||
value = new Date(value as string);
|
value = new Date(value as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("cardAttrValue", value);
|
|
||||||
console.log("value type", typeof value);
|
|
||||||
return {
|
return {
|
||||||
...values,
|
...values,
|
||||||
[cardAttribute.attribute.name]: value,
|
[cardAttribute.attribute.name]: value,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const InlineButton = ({ children, onClick, ...props }: Props) => {
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<Group gap="sm">
|
<Group gap="sm" wrap={"nowrap"}>
|
||||||
{children}
|
{children}
|
||||||
</Group>
|
</Group>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
18
src/pages/CardsPage/tabs/ShippingTab/ShippingTab.module.css
Normal file
18
src/pages/CardsPage/tabs/ShippingTab/ShippingTab.module.css
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.icon {
|
||||||
|
width: rem(13px);
|
||||||
|
height: auto;
|
||||||
|
vertical-align: rem(-1px);
|
||||||
|
margin-right: rem(8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandIcon {
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandIconRotated {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.productsTableBorder {
|
||||||
|
border-bottom: solid 1px var(--mantine-color-dark-5);
|
||||||
|
}
|
||||||
@@ -1,27 +1,31 @@
|
|||||||
import useShippingTableColumns from "../hooks/shippingTableColumns.tsx";
|
|
||||||
import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
|
|
||||||
import { BoxSchema, ShippingService } from "../../../../../client";
|
import { BoxSchema, ShippingService } from "../../../../../client";
|
||||||
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
|
import { IconBox, IconChevronRight, IconPlus, IconTrash } from "@tabler/icons-react";
|
||||||
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
|
||||||
import { MRT_TableOptions } from "mantine-react-table";
|
|
||||||
import { modals } from "@mantine/modals";
|
|
||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
|
||||||
import useUpdateCard from "../hooks/useUpdateCard.tsx";
|
import useUpdateCard from "../hooks/useUpdateCard.tsx";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
|
import { DataTable } from "mantine-datatable";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import classes from "../ShippingTab.module.css";
|
||||||
|
import "mantine-datatable/styles.css";
|
||||||
|
import { useState } from "react";
|
||||||
|
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
||||||
|
import { Group, rem, Text } from "@mantine/core";
|
||||||
|
import { ShippingProductParentData } from "../types/ShippingProductData.tsx";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import InlineShippingButton from "./InlineShippingButton.tsx";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
items: BoxSchema[];
|
items: BoxSchema[];
|
||||||
|
onCreateShippingProduct: (values: ShippingProductParentData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoxesTable = ({ items }: Props) => {
|
const BoxesTable = ({ items, onCreateShippingProduct }: Props) => {
|
||||||
const columns = useShippingTableColumns<BoxSchema>({ isBox: true });
|
|
||||||
const { update } = useUpdateCard();
|
const { update } = useUpdateCard();
|
||||||
const { selectedCard: card } = useCardPageContext();
|
const [boxIds, setBoxIds] = useState<number[]>([]);
|
||||||
|
|
||||||
const onDeleteClick = (box: BoxSchema) => {
|
const onDeleteBox = (boxId: number) => {
|
||||||
ShippingService.deleteBox({
|
ShippingService.deleteBox({
|
||||||
boxId: box.id,
|
boxId,
|
||||||
})
|
})
|
||||||
.then(({ ok, message }) => {
|
.then(({ ok, message }) => {
|
||||||
notifications.guess(ok, { message });
|
notifications.guess(ok, { message });
|
||||||
@@ -30,55 +34,92 @@ const BoxesTable = ({ items }: Props) => {
|
|||||||
.catch(err => console.log(err));
|
.catch(err => console.log(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEditClick = (box: BoxSchema) => {
|
const onDeleteBoxClick = (box: BoxSchema) => {
|
||||||
if (!card) return;
|
if (box.shippingProducts.length === 0) {
|
||||||
modals.openContextModal({
|
onDeleteBox(box.id);
|
||||||
modal: "shippingProductModal",
|
return;
|
||||||
title: "Редактирование короба",
|
}
|
||||||
withCloseButton: false,
|
|
||||||
innerProps: {
|
modals.openConfirmModal({
|
||||||
card,
|
title: "Удаление короба",
|
||||||
updateOnSubmit: update,
|
children: <Text size="sm">Вы уверены что хотите удалить короб?</Text>,
|
||||||
isBox: true,
|
labels: { confirm: "Да", cancel: "Нет" },
|
||||||
shippingData: {
|
confirmProps: { color: "red" },
|
||||||
boxId: box.id,
|
onConfirm: () => onDeleteBox(box.id),
|
||||||
productId: box.product?.id,
|
|
||||||
quantity: box.quantity,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getBoxContent = (box: BoxSchema) => {
|
||||||
|
if (box.shippingProducts.length === 0) {
|
||||||
return (
|
return (
|
||||||
<BaseTable
|
<Text>Пустой</Text>
|
||||||
data={items}
|
);
|
||||||
columns={columns}
|
|
||||||
restProps={
|
|
||||||
{
|
|
||||||
enableSorting: false,
|
|
||||||
enableColumnActions: false,
|
|
||||||
enableRowActions: true,
|
|
||||||
positionActionsColumn: "last",
|
|
||||||
renderRowActions: ({ row }) => (
|
|
||||||
<Flex gap="md">
|
|
||||||
<Tooltip label="Удалить">
|
|
||||||
<ActionIcon
|
|
||||||
onClick={() => onDeleteClick(row.original)}
|
|
||||||
variant={"default"}>
|
|
||||||
<IconTrash />
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip label="Редактировать">
|
|
||||||
<ActionIcon
|
|
||||||
onClick={() => onEditClick(row.original)}
|
|
||||||
variant={"default"}>
|
|
||||||
<IconEdit />
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
|
||||||
),
|
|
||||||
} as MRT_TableOptions<BoxSchema>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ShippingProductsTable items={box.shippingProducts} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBoxActions = (box: BoxSchema) => {
|
||||||
|
return (
|
||||||
|
<Group wrap={"nowrap"} gap={rem(10)}>
|
||||||
|
<InlineShippingButton onClick={() => onCreateShippingProduct({ boxId: box.id })}>
|
||||||
|
<IconPlus />
|
||||||
|
Товар
|
||||||
|
</InlineShippingButton>
|
||||||
|
<InlineShippingButton onClick={() => onDeleteBoxClick(box)}>
|
||||||
|
<IconTrash />
|
||||||
|
</InlineShippingButton>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isBoxExpandable = (box: BoxSchema) => {
|
||||||
|
const isExpandable = box.shippingProducts.length > 0;
|
||||||
|
if (!isExpandable && boxIds.includes(box.id)) {
|
||||||
|
setBoxIds(boxIds.filter(boxId => boxId !== box.id));
|
||||||
|
}
|
||||||
|
return isExpandable;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataTable
|
||||||
|
noHeader
|
||||||
|
withTableBorder
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
accessor: "id",
|
||||||
|
title: "Короб",
|
||||||
|
noWrap: true,
|
||||||
|
render: (box) => (
|
||||||
|
<>
|
||||||
|
{isBoxExpandable(box) && (
|
||||||
|
<IconChevronRight
|
||||||
|
className={clsx(classes.icon, classes.expandIcon, {
|
||||||
|
[classes.expandIconRotated]: boxIds?.includes(box.id),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<IconBox className={classes.icon} />
|
||||||
|
<span>Короб К{box.id}</span>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: "actions",
|
||||||
|
title: "",
|
||||||
|
width: "0%",
|
||||||
|
render: getBoxActions,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
records={items?.sort((a, b) => a.id - b.id)}
|
||||||
|
rowExpansion={{
|
||||||
|
allowMultiple: true,
|
||||||
|
expanded: { recordIds: boxIds, onRecordIdsChange: setBoxIds },
|
||||||
|
expandable: ({ record }) => isBoxExpandable(record),
|
||||||
|
content: ({ record }) => getBoxContent(record),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import React, { ReactNode } from "react";
|
||||||
|
import { Button, ButtonProps, Group } from "@mantine/core";
|
||||||
|
|
||||||
|
interface Props extends ButtonProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InlineShippingButton = ({ children, onClick, ...props }: Props) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onClick && onClick();
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<Group gap="sm" wrap={"nowrap"}>
|
||||||
|
{children}
|
||||||
|
</Group>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InlineShippingButton;
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
import useShippingTableColumns from "../hooks/shippingTableColumns.tsx";
|
import useShippingTableColumns from "../hooks/shippingTableColumns.tsx";
|
||||||
import { BaseTable } from "../../../../../components/BaseTable/BaseTable.tsx";
|
import { ShippingProductSchema } from "../../../../../client";
|
||||||
import { ShippingProductSchema, ShippingService } from "../../../../../client";
|
import { Box } from "@mantine/core";
|
||||||
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
|
import { DataTable } from "mantine-datatable";
|
||||||
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
import clsx from "clsx";
|
||||||
import { MRT_TableOptions } from "mantine-react-table";
|
import "mantine-datatable/styles.css";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import classes from "../ShippingTab.module.css";
|
||||||
import useUpdateCard from "../hooks/useUpdateCard.tsx";
|
|
||||||
import { modals } from "@mantine/modals";
|
|
||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -15,72 +12,18 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ShippingProductsTable = ({ items }: Props) => {
|
const ShippingProductsTable = ({ items }: Props) => {
|
||||||
const columns = useShippingTableColumns<ShippingProductSchema>({ isBox: false });
|
const columns = useShippingTableColumns();
|
||||||
const { update } = useUpdateCard();
|
|
||||||
const { selectedCard: card } = useCardPageContext();
|
|
||||||
|
|
||||||
const onDeleteClick = (shippingProduct: ShippingProductSchema) => {
|
|
||||||
ShippingService.deleteShippingProduct({
|
|
||||||
shippingProductId: shippingProduct.id,
|
|
||||||
})
|
|
||||||
.then(({ ok, message }) => {
|
|
||||||
notifications.guess(ok, { message });
|
|
||||||
update();
|
|
||||||
})
|
|
||||||
.catch(err => console.log(err));
|
|
||||||
};
|
|
||||||
|
|
||||||
const onEditClick = (shippingProduct: ShippingProductSchema) => {
|
|
||||||
if (!card) return;
|
|
||||||
modals.openContextModal({
|
|
||||||
modal: "shippingProductModal",
|
|
||||||
title: "Редактирование товара на паллете",
|
|
||||||
withCloseButton: false,
|
|
||||||
innerProps: {
|
|
||||||
card,
|
|
||||||
updateOnSubmit: update,
|
|
||||||
isBox: false,
|
|
||||||
shippingData: {
|
|
||||||
shippingProductId: shippingProduct.id,
|
|
||||||
productId: shippingProduct.product.id,
|
|
||||||
quantity: shippingProduct.quantity,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseTable
|
<Box>
|
||||||
data={items}
|
<DataTable
|
||||||
|
withTableBorder
|
||||||
|
withColumnBorders
|
||||||
columns={columns}
|
columns={columns}
|
||||||
restProps={
|
records={items}
|
||||||
{
|
className={clsx(classes.productsTableBorder)}
|
||||||
enableSorting: false,
|
|
||||||
enableColumnActions: false,
|
|
||||||
enableRowActions: true,
|
|
||||||
enableRowNumbers: true,
|
|
||||||
positionActionsColumn: "last",
|
|
||||||
renderRowActions: ({ row }) => (
|
|
||||||
<Flex gap="md">
|
|
||||||
<Tooltip label="Удалить">
|
|
||||||
<ActionIcon
|
|
||||||
onClick={() => onDeleteClick(row.original)}
|
|
||||||
variant={"default"}>
|
|
||||||
<IconTrash />
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip label="Редактировать">
|
|
||||||
<ActionIcon
|
|
||||||
onClick={() => onEditClick(row.original)}
|
|
||||||
variant={"default"}>
|
|
||||||
<IconEdit />
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
|
||||||
),
|
|
||||||
} as MRT_TableOptions<ShippingProductSchema>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
||||||
import { Accordion, ActionIcon, Button, Center, Group, rem, Stack, Title, Tooltip } from "@mantine/core";
|
import { Flex, rem, Stack } from "@mantine/core";
|
||||||
import { BoxSchema, PalletSchema, ShippingProductSchema } from "../../../../../client";
|
import { BoxSchema, PalletSchema, ShippingProductSchema } from "../../../../../client";
|
||||||
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
import ShippingProductsTable from "./ShippingProductsTable.tsx";
|
||||||
import BoxesTable from "./BoxesTable.tsx";
|
import BoxesTable from "./BoxesTable.tsx";
|
||||||
import { IconBox, IconPlus, IconSpace, IconTrash } from "@tabler/icons-react";
|
import { IconChevronRight, IconPlus, IconSpace, IconTrash } from "@tabler/icons-react";
|
||||||
import useShipping from "../hooks/useShipping.tsx";
|
import useShipping from "../hooks/useShipping.tsx";
|
||||||
|
import { DataTable } from "mantine-datatable";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import "mantine-datatable/styles.css";
|
||||||
|
import classes from "../ShippingTab.module.css";
|
||||||
|
import InlineShippingButton from "./InlineShippingButton.tsx";
|
||||||
|
|
||||||
const ShippingTree = () => {
|
const ShippingTree = () => {
|
||||||
const { selectedCard: card } = useCardPageContext();
|
const { selectedCard: card } = useCardPageContext();
|
||||||
@@ -14,91 +19,59 @@ const ShippingTree = () => {
|
|||||||
onCreateShippingProduct,
|
onCreateShippingProduct,
|
||||||
onDeletePalletClick,
|
onDeletePalletClick,
|
||||||
palletIds,
|
palletIds,
|
||||||
|
setPalletIds,
|
||||||
} = useShipping();
|
} = useShipping();
|
||||||
|
|
||||||
const sortById = (data?: PalletSchema[] | BoxSchema[] | ShippingProductSchema[]) => {
|
const sortById = (data?: PalletSchema[] | BoxSchema[] | ShippingProductSchema[]) => {
|
||||||
return data?.sort((a, b) => a.id - b.id);
|
return data?.sort((a, b) => a.id - b.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPallets = () => {
|
const removePalletButton = (pallet: PalletSchema) => {
|
||||||
const sortedPallets = sortById(card?.pallets) as PalletSchema[];
|
|
||||||
const pallets = sortedPallets?.map((pallet => {
|
|
||||||
palletIds.push(pallet.id.toString());
|
|
||||||
return (
|
return (
|
||||||
<Accordion.Item key={pallet.id} value={pallet.id.toString()}>
|
<InlineShippingButton onClick={() => onDeletePalletClick(pallet)}>
|
||||||
<Center>
|
|
||||||
<Accordion.Control icon={<IconSpace />}>
|
|
||||||
Паллет - П{pallet.id}
|
|
||||||
</Accordion.Control>
|
|
||||||
{removePalletButton(pallet.id)}
|
|
||||||
</Center>
|
|
||||||
<Accordion.Panel>
|
|
||||||
{getPalletContent(pallet)}
|
|
||||||
</Accordion.Panel>
|
|
||||||
</Accordion.Item>
|
|
||||||
);
|
|
||||||
})) ?? [];
|
|
||||||
|
|
||||||
if (card?.boxes && card?.boxes.length > 0) {
|
|
||||||
const boxes = card?.boxes.sort((b1, b2) => (b1.id - b2.id));
|
|
||||||
const itemValue = "noPallets";
|
|
||||||
const boxesWithoutPallet = (
|
|
||||||
<Accordion.Item key={-1} value={itemValue}>
|
|
||||||
<Accordion.Control icon={<IconBox />}>
|
|
||||||
Короба без паллетов
|
|
||||||
</Accordion.Control>
|
|
||||||
<Accordion.Panel>
|
|
||||||
<BoxesTable items={boxes} />
|
|
||||||
</Accordion.Panel>
|
|
||||||
</Accordion.Item>
|
|
||||||
);
|
|
||||||
pallets.unshift(boxesWithoutPallet);
|
|
||||||
palletIds.push(itemValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pallets;
|
|
||||||
};
|
|
||||||
|
|
||||||
const removePalletButton = (palletId: number) => {
|
|
||||||
return (
|
|
||||||
<Tooltip label="Удалить паллет">
|
|
||||||
<ActionIcon
|
|
||||||
variant={"default"}
|
|
||||||
onClick={() => onDeletePalletClick(palletId)}
|
|
||||||
mx={"md"}
|
|
||||||
>
|
|
||||||
<IconTrash />
|
<IconTrash />
|
||||||
</ActionIcon>
|
</InlineShippingButton>
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createBoxOrShippingProductButton = (palletId: number, isBox: boolean) => {
|
const createBoxOrShippingProductButton = (palletId: number, isBox: boolean) => {
|
||||||
const createButtonLabel = isBox ? "Добавить короб" : "Добавить товар";
|
const createButtonLabel = isBox ? "Короб" : "Товар";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<InlineShippingButton
|
||||||
variant={"default"}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isBox) {
|
if (isBox) {
|
||||||
onCreateBoxInPallet(palletId);
|
onCreateBoxInPallet(palletId);
|
||||||
} else {
|
} else {
|
||||||
onCreateShippingProduct(palletId);
|
onCreateShippingProduct({ palletId });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Group gap={rem(5)}>
|
|
||||||
<IconPlus />
|
<IconPlus />
|
||||||
{createButtonLabel}
|
{createButtonLabel}
|
||||||
</Group>
|
</InlineShippingButton>
|
||||||
</Button>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPalletContent = (pallet: PalletSchema) => {
|
const getPalletContent = (pallet: PalletSchema) => {
|
||||||
|
const isBox = pallet.boxes.length > 0;
|
||||||
|
|
||||||
|
const boxes = sortById(pallet.boxes) as BoxSchema[];
|
||||||
|
const shippingProducts = sortById(pallet.shippingProducts) as ShippingProductSchema[];
|
||||||
|
|
||||||
|
if (isBox) {
|
||||||
|
return (
|
||||||
|
<BoxesTable items={boxes} onCreateShippingProduct={onCreateShippingProduct} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ShippingProductsTable items={shippingProducts} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPalletActions = (pallet: PalletSchema) => {
|
||||||
const isEmpty = pallet.boxes.length === 0 && pallet.shippingProducts.length === 0;
|
const isEmpty = pallet.boxes.length === 0 && pallet.shippingProducts.length === 0;
|
||||||
const isBox = pallet.boxes.length > 0;
|
const isBox = pallet.boxes.length > 0;
|
||||||
const title = isEmpty ? "Пустой" : isBox ? "Короба" : "Товары";
|
|
||||||
|
|
||||||
let palletButtons;
|
let palletButtons;
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
@@ -112,39 +85,77 @@ const ShippingTree = () => {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const boxes = sortById(pallet.boxes) as BoxSchema[];
|
|
||||||
const shippingProducts = sortById(pallet.shippingProducts) as ShippingProductSchema[];
|
|
||||||
|
|
||||||
let table;
|
|
||||||
if (!isEmpty) {
|
|
||||||
if (isBox) {
|
|
||||||
table = (<BoxesTable items={boxes} />);
|
|
||||||
} else {
|
|
||||||
table = (<ShippingProductsTable items={shippingProducts} />);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap={rem(5)}>
|
<Flex
|
||||||
<Group justify={"space-between"}>
|
gap={rem(10)}
|
||||||
<Title order={6}>{title}</Title>
|
wrap={"nowrap"}
|
||||||
<Group gap={rem(10)}>
|
direction={"row-reverse"}
|
||||||
|
>
|
||||||
|
{removePalletButton(pallet)}
|
||||||
{...palletButtons}
|
{...palletButtons}
|
||||||
</Group>
|
</Flex>
|
||||||
</Group>
|
|
||||||
{table}
|
|
||||||
</Stack>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isPalletExpandable = (pallet: PalletSchema) => {
|
||||||
|
const isExpandable = pallet.boxes.length !== 0 || pallet.shippingProducts.length !== 0;
|
||||||
|
if (!isExpandable && palletIds.includes(pallet.id)) {
|
||||||
|
setPalletIds(palletIds.filter(palletId => palletId !== pallet.id));
|
||||||
|
}
|
||||||
|
return isExpandable;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (card?.boxes?.length === 0 && card?.pallets?.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Stack gap={0}>
|
||||||
multiple={true}
|
{card?.boxes && (
|
||||||
defaultValue={palletIds}
|
<BoxesTable items={card?.boxes} onCreateShippingProduct={onCreateShippingProduct} />
|
||||||
bd={"solid 1px gray"}
|
)}
|
||||||
>
|
<DataTable
|
||||||
{getPallets()}
|
noHeader
|
||||||
</Accordion>
|
withTableBorder
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
accessor: "id",
|
||||||
|
title: "Паллет",
|
||||||
|
noWrap: true,
|
||||||
|
render: (pallet) => {
|
||||||
|
const isExpandable = isPalletExpandable(pallet);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isExpandable && (
|
||||||
|
<IconChevronRight
|
||||||
|
className={clsx(classes.icon, classes.expandIcon, {
|
||||||
|
[classes.expandIconRotated]: palletIds?.includes(pallet.id),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<IconSpace className={classes.icon} />
|
||||||
|
<span>Паллет П{pallet.id}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: "actions",
|
||||||
|
title: "",
|
||||||
|
width: "0%",
|
||||||
|
render: getPalletActions,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
records={card?.pallets?.sort((a, b) => a.id - b.id)}
|
||||||
|
rowExpansion={{
|
||||||
|
allowMultiple: true,
|
||||||
|
expanded: { recordIds: palletIds, onRecordIdsChange: setPalletIds },
|
||||||
|
expandable: ({ record }) => isPalletExpandable(record),
|
||||||
|
content: ({ record }) => getPalletContent(record),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,89 @@
|
|||||||
import { useMemo } from "react";
|
import { DataTableColumn } from "mantine-datatable";
|
||||||
import { MRT_ColumnDef, MRT_RowData } from "mantine-react-table";
|
import { ShippingProductSchema, ShippingService } from "../../../../../client";
|
||||||
|
import { ActionIcon, Flex, Tooltip } from "@mantine/core";
|
||||||
|
import { IconEdit, IconTrash } from "@tabler/icons-react";
|
||||||
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
|
import { modals } from "@mantine/modals";
|
||||||
|
import useUpdateCard from "./useUpdateCard.tsx";
|
||||||
|
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
||||||
|
|
||||||
type Props = {
|
const useShippingTableColumns = () => {
|
||||||
isBox: boolean;
|
const { update } = useUpdateCard();
|
||||||
}
|
const { selectedCard: card } = useCardPageContext();
|
||||||
|
|
||||||
const useShippingTableColumns = <T extends MRT_RowData>({ isBox }: Props) => {
|
const onDeleteClick = (shippingProduct: ShippingProductSchema) => {
|
||||||
const hideBoxColumns = ["id"];
|
ShippingService.deleteShippingProduct({
|
||||||
|
shippingProductId: shippingProduct.id,
|
||||||
|
})
|
||||||
|
.then(({ ok, message }) => {
|
||||||
|
notifications.guess(ok, { message });
|
||||||
|
update();
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
};
|
||||||
|
|
||||||
return useMemo<MRT_ColumnDef<T>[]>(
|
const onEditClick = (shippingProduct: ShippingProductSchema) => {
|
||||||
() => [
|
if (!card) return;
|
||||||
|
modals.openContextModal({
|
||||||
|
modal: "shippingProductModal",
|
||||||
|
title: "Редактирование товара",
|
||||||
|
withCloseButton: false,
|
||||||
|
innerProps: {
|
||||||
|
card,
|
||||||
|
updateOnSubmit: update,
|
||||||
|
shippingData: {
|
||||||
|
shippingProductId: shippingProduct.id,
|
||||||
|
productId: shippingProduct.product.id,
|
||||||
|
quantity: shippingProduct.quantity,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
header: "ID",
|
title: "Название",
|
||||||
accessorKey: "id",
|
accessor: "product.name",
|
||||||
Cell: ({ row }) => `K${row.original.id}`,
|
render: shippingProduct => shippingProduct.product?.name ?? "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Название",
|
title: "Артикул",
|
||||||
accessorKey: "product.name",
|
accessor: "product.article",
|
||||||
Cell: ({ row }) => row.original.product?.name ?? "-",
|
render: shippingProduct => shippingProduct.product?.article ?? "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Артикул",
|
title: "Размер",
|
||||||
accessorKey: "product.article",
|
accessor: "product.size",
|
||||||
Cell: ({ row }) => row.original.product?.article ?? "-",
|
render: shippingProduct => shippingProduct.product?.size ?? "-",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Размер",
|
title: "Количество",
|
||||||
accessorKey: "product.size",
|
accessor: "quantity",
|
||||||
Cell: ({ row }) => row.original.product?.size ?? "-",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Количество",
|
accessor: "actions",
|
||||||
accessorKey: "quantity",
|
title: "",
|
||||||
|
width: "0%",
|
||||||
|
render: shippingProduct => (
|
||||||
|
<Flex gap="md">
|
||||||
|
<Tooltip label="Удалить">
|
||||||
|
<ActionIcon
|
||||||
|
onClick={() => onDeleteClick(shippingProduct)}
|
||||||
|
variant={"default"}>
|
||||||
|
<IconTrash />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip label="Редактировать">
|
||||||
|
<ActionIcon
|
||||||
|
onClick={() => onEditClick(shippingProduct)}
|
||||||
|
variant={"default"}>
|
||||||
|
<IconEdit />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
],
|
] as DataTableColumn<ShippingProductSchema>[];
|
||||||
[],
|
|
||||||
).filter(
|
|
||||||
columnDef => isBox || !hideBoxColumns.includes(columnDef.accessorKey || ""),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useShippingTableColumns;
|
export default useShippingTableColumns;
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
import { useCardPageContext } from "../../../contexts/CardPageContext.tsx";
|
||||||
import { CreateBoxInCardSchema, CreateBoxInPalletSchema, ShippingService } from "../../../../../client";
|
import {
|
||||||
|
CreateBoxInCardSchema,
|
||||||
|
CreateBoxInPalletSchema, PalletSchema,
|
||||||
|
ShippingService,
|
||||||
|
} from "../../../../../client";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
import { Text } from "@mantine/core";
|
import { Text } from "@mantine/core";
|
||||||
import useUpdateCard from "./useUpdateCard.tsx";
|
import useUpdateCard from "./useUpdateCard.tsx";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ShippingProductParentData } from "../types/ShippingProductData.tsx";
|
||||||
|
|
||||||
const useShipping = () => {
|
const useShipping = () => {
|
||||||
const { selectedCard: card } = useCardPageContext();
|
const { selectedCard: card } = useCardPageContext();
|
||||||
const { update } = useUpdateCard();
|
const { update } = useUpdateCard();
|
||||||
const palletIds: string[] = [];
|
const [palletIds, setPalletIds] = useState<number[]>([]);
|
||||||
|
|
||||||
const onCreatePalletClick = () => {
|
const onCreatePalletClick = () => {
|
||||||
if (!card) return;
|
if (!card) return;
|
||||||
@@ -34,19 +40,24 @@ const useShipping = () => {
|
|||||||
.catch(err => console.log(err));
|
.catch(err => console.log(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeletePalletClick = (palletId: number) => {
|
const onDeletePalletClick = (pallet: PalletSchema) => {
|
||||||
if (!card) return;
|
if (!card) return;
|
||||||
|
if (pallet.shippingProducts.length === 0 && pallet.boxes.length === 0) {
|
||||||
|
onDeletePallet(pallet.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
modals.openConfirmModal({
|
modals.openConfirmModal({
|
||||||
title: "Удаление паллета",
|
title: "Удаление паллета",
|
||||||
children: <Text size="sm">Вы уверены что хотите удалить паллет?</Text>,
|
children: <Text size="sm">Вы уверены что хотите удалить паллет?</Text>,
|
||||||
labels: { confirm: "Да", cancel: "Нет" },
|
labels: { confirm: "Да", cancel: "Нет" },
|
||||||
confirmProps: { color: "red" },
|
confirmProps: { color: "red" },
|
||||||
onConfirm: () => onDeletePallet(palletId),
|
onConfirm: () => onDeletePallet(pallet.id),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCreateBox = (data: CreateBoxInPalletSchema | CreateBoxInCardSchema) => {
|
const onCreateBox = (data: CreateBoxInPalletSchema | CreateBoxInCardSchema) => {
|
||||||
ShippingService.updateBox({
|
ShippingService.createBox({
|
||||||
requestBody: {
|
requestBody: {
|
||||||
data,
|
data,
|
||||||
},
|
},
|
||||||
@@ -66,18 +77,20 @@ const useShipping = () => {
|
|||||||
onCreateBox({ palletId });
|
onCreateBox({ palletId });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCreateShippingProduct = (palletId: number) => {
|
const onCreateShippingProduct = ({ palletId, boxId }: ShippingProductParentData) => {
|
||||||
if (!card) return;
|
if (!card) return;
|
||||||
|
const postfix = palletId ? "на паллет" : "в короб";
|
||||||
|
|
||||||
modals.openContextModal({
|
modals.openContextModal({
|
||||||
modal: "shippingProductModal",
|
modal: "shippingProductModal",
|
||||||
title: "Добавление товара на паллет",
|
title: "Добавление товара " + postfix,
|
||||||
withCloseButton: false,
|
withCloseButton: false,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
card,
|
card,
|
||||||
updateOnSubmit: update,
|
updateOnSubmit: update,
|
||||||
isBox: false,
|
|
||||||
shippingData: {
|
shippingData: {
|
||||||
palletId,
|
palletId,
|
||||||
|
boxId,
|
||||||
productId: null,
|
productId: null,
|
||||||
quantity: null,
|
quantity: null,
|
||||||
},
|
},
|
||||||
@@ -92,6 +105,7 @@ const useShipping = () => {
|
|||||||
onCreatePalletClick,
|
onCreatePalletClick,
|
||||||
onDeletePalletClick,
|
onDeletePalletClick,
|
||||||
palletIds,
|
palletIds,
|
||||||
|
setPalletIds,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,11 @@ import { ContextModalProps } from "@mantine/modals";
|
|||||||
import { Button, Flex, NumberInput, rem, Text } from "@mantine/core";
|
import { Button, Flex, NumberInput, rem, Text } from "@mantine/core";
|
||||||
import getRestProducts from "../utils/getRestProducts.tsx";
|
import getRestProducts from "../utils/getRestProducts.tsx";
|
||||||
import {
|
import {
|
||||||
CreateBoxInCardSchema,
|
|
||||||
CreateBoxInPalletSchema,
|
|
||||||
CreateShippingProductSchema,
|
|
||||||
CardProductSchema,
|
CardProductSchema,
|
||||||
CardSchema,
|
CardSchema,
|
||||||
|
CreateShippingProductSchema,
|
||||||
ProductSchema,
|
ProductSchema,
|
||||||
ShippingService,
|
ShippingService,
|
||||||
UpdateBoxSchema,
|
|
||||||
UpdateShippingProductSchema,
|
UpdateShippingProductSchema,
|
||||||
} from "../../../../../client";
|
} from "../../../../../client";
|
||||||
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
import { notifications } from "../../../../../shared/lib/notifications.ts";
|
||||||
@@ -22,7 +19,6 @@ import ShippingProductSelect from "../components/ShippingProductSelect.tsx";
|
|||||||
type Props = {
|
type Props = {
|
||||||
updateOnSubmit: () => void;
|
updateOnSubmit: () => void;
|
||||||
card: CardSchema;
|
card: CardSchema;
|
||||||
isBox: boolean;
|
|
||||||
shippingData: Partial<ShippingData>;
|
shippingData: Partial<ShippingData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,31 +61,13 @@ const ShippingProductModal = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const data = getRestProducts({
|
const data = getRestProducts({
|
||||||
card: innerProps.card,
|
card: innerProps.card,
|
||||||
unaccountedValues: innerProps.shippingData as UpdateShippingProductSchema | UpdateBoxSchema,
|
shippingProductId: (innerProps.shippingData as UpdateShippingProductSchema).shippingProductId,
|
||||||
});
|
});
|
||||||
setRestProducts(data.restProducts);
|
setRestProducts(data.restProducts);
|
||||||
setRestProductSelectData(data.restProductsSelectData);
|
setRestProductSelectData(data.restProductsSelectData);
|
||||||
}, [innerProps.card]);
|
}, [innerProps.card]);
|
||||||
|
|
||||||
const updateBox = () => {
|
const onSubmit = () => {
|
||||||
const data = {
|
|
||||||
...innerProps.shippingData,
|
|
||||||
...form.values,
|
|
||||||
productId: form.values.product?.id,
|
|
||||||
} as CreateBoxInPalletSchema | CreateBoxInCardSchema | UpdateBoxSchema;
|
|
||||||
|
|
||||||
ShippingService.updateBox({
|
|
||||||
requestBody: { data },
|
|
||||||
})
|
|
||||||
.then(({ ok, message }) => {
|
|
||||||
notifications.guess(ok, { message: message });
|
|
||||||
innerProps.updateOnSubmit();
|
|
||||||
if (ok) context.closeContextModal(id);
|
|
||||||
})
|
|
||||||
.catch(err => console.log(err));
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateShippingProduct = () => {
|
|
||||||
const data = {
|
const data = {
|
||||||
...innerProps.shippingData,
|
...innerProps.shippingData,
|
||||||
...form.values,
|
...form.values,
|
||||||
@@ -107,14 +85,6 @@ const ShippingProductModal = ({
|
|||||||
.catch(err => console.log(err));
|
.catch(err => console.log(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = () => {
|
|
||||||
if (innerProps.isBox) {
|
|
||||||
updateBox();
|
|
||||||
} else {
|
|
||||||
updateShippingProduct();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getRestQuantityText = () => {
|
const getRestQuantityText = () => {
|
||||||
if (!form.values.product) return;
|
if (!form.values.product) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import {
|
import { CreateShippingProductSchema, ProductSchema, UpdateShippingProductSchema } from "../../../../../client";
|
||||||
CreateShippingProductSchema,
|
|
||||||
ProductSchema,
|
|
||||||
UpdateBoxSchema,
|
|
||||||
UpdateShippingProductSchema,
|
|
||||||
} from "../../../../../client";
|
|
||||||
|
|
||||||
export type ShippingModalForm = {
|
export type ShippingModalForm = {
|
||||||
quantity: number;
|
quantity: number;
|
||||||
product?: ProductSchema | null;
|
product?: ProductSchema | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShippingData =
|
export type ShippingData = CreateShippingProductSchema | UpdateShippingProductSchema;
|
||||||
UpdateBoxSchema
|
|
||||||
| CreateShippingProductSchema
|
export type ShippingProductParentData = {
|
||||||
| UpdateShippingProductSchema;
|
palletId?: number;
|
||||||
|
boxId?: number;
|
||||||
|
}
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
import { CardProductSchema, CardSchema, ProductSchema } from "../../../../../client";
|
import { BoxSchema, CardProductSchema, CardSchema, ProductSchema } from "../../../../../client";
|
||||||
|
|
||||||
type UnaccountedValues = {
|
|
||||||
boxId?: number | null;
|
|
||||||
shippingProductId?: number | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
card?: CardSchema;
|
card?: CardSchema;
|
||||||
unaccountedValues: UnaccountedValues;
|
shippingProductId?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRestProducts = ({
|
const getRestProducts = ({
|
||||||
card,
|
card,
|
||||||
unaccountedValues,
|
shippingProductId,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const totalProducts = new Map(
|
const totalProducts = new Map(
|
||||||
card?.products.map(product => product && [product.product.id, product]),
|
card?.products.map(product => product && [product.product.id, product]),
|
||||||
@@ -30,20 +26,23 @@ const getRestProducts = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
card?.boxes?.forEach((box) => {
|
const accountBoxes = (boxes?: BoxSchema[]) => {
|
||||||
if (!box.product || box.id === unaccountedValues.boxId) return;
|
boxes?.forEach((box) => {
|
||||||
accountProduct(box.product, box.quantity);
|
box.shippingProducts.forEach((shippingProduct) => {
|
||||||
|
if (!shippingProduct.product || shippingProduct.id === shippingProductId) return;
|
||||||
|
accountProduct(shippingProduct.product, shippingProduct.quantity);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
accountBoxes(card?.boxes);
|
||||||
|
|
||||||
card?.pallets?.forEach(pallet => {
|
card?.pallets?.forEach(pallet => {
|
||||||
pallet.shippingProducts.forEach(shippingProduct => {
|
pallet.shippingProducts.forEach(shippingProduct => {
|
||||||
if (shippingProduct.id === unaccountedValues.shippingProductId) return;
|
if (shippingProduct.id === shippingProductId) return;
|
||||||
accountProduct(shippingProduct.product, shippingProduct.quantity);
|
accountProduct(shippingProduct.product, shippingProduct.quantity);
|
||||||
});
|
});
|
||||||
pallet.boxes.forEach((box) => {
|
accountBoxes(pallet.boxes);
|
||||||
if (!box.product || box.id === unaccountedValues.boxId) return;
|
|
||||||
accountProduct(box.product, box.quantity);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const restProducts = new Map<number, CardProductSchema>();
|
const restProducts = new Map<number, CardProductSchema>();
|
||||||
|
|||||||
Reference in New Issue
Block a user