feat: searchable product select and department select

This commit is contained in:
2025-01-31 20:18:01 +04:00
parent 52619f119f
commit 0a4e20e888
7 changed files with 126 additions and 156 deletions

View File

@@ -73,6 +73,7 @@ const DepartmentSelect = ({
value={getDepartmentValue()}
onChange={setDepartmentValue}
label={"Родительский департамент/отдел"}
searchable
/>
);
};

View File

@@ -0,0 +1,40 @@
import { ProductSchema } from "../../../../../client";
import { FC, useState } from "react";
import ObjectSelect, { ObjectSelectProps } from "../../../../../components/ObjectSelect/ObjectSelect.tsx";
import getRenderOptions from "../../../../../components/ProductSelect/utils/getRenderOptions.tsx";
type Props = Omit<ObjectSelectProps<ProductSchema>, "searchValue" | "onSearchChange">;
const ShippingProductSelect: FC<Props> = (props: Props) => {
const [search, setSearch] = useState("");
const getFilteredData = () => {
const searchValue: string = search.toLowerCase();
const data: ProductSchema[] = props.data.filter(product => {
return (
product.name.toLowerCase().includes(searchValue) ||
product.article?.toLowerCase().includes(searchValue) ||
product.barcodes && product.barcodes[0].toLowerCase().includes(searchValue)
);
});
return data;
};
return (
<ObjectSelect
label={"Товар"}
placeholder={"Выберите товар"}
searchable
{...props}
data={getFilteredData()}
searchValue={search}
onSearchChange={setSearch}
renderOption={getRenderOptions(props.data)}
filter={({ options }) => options}
/>
);
};
export default ShippingProductSelect;

View File

@@ -1,6 +1,6 @@
import { useForm } from "@mantine/form";
import { ContextModalProps } from "@mantine/modals";
import { Button, Flex, NumberInput, rem, Select, Text } from "@mantine/core";
import { Button, Flex, NumberInput, rem, Text } from "@mantine/core";
import getRestProducts from "../utils/getRestProducts.tsx";
import {
CreateBoxInDealSchema,
@@ -8,14 +8,15 @@ import {
CreateShippingProductSchema,
DealProductSchema,
DealSchema,
ProductSchema,
ShippingService,
UpdateBoxSchema,
UpdateShippingProductSchema,
} from "../../../../../client";
import { notifications } from "../../../../../shared/lib/notifications.ts";
import { ShippingData, ShippingModalForm, ShippingProductOption } from "../types/ShippingProductData.tsx";
import { ShippingData, ShippingModalForm } from "../types/ShippingProductData.tsx";
import { useEffect, useState } from "react";
import ShippingProductSelect from "../components/ShippingProductSelect.tsx";
type Props = {
@@ -31,11 +32,11 @@ const ShippingProductModal = ({
innerProps,
}: ContextModalProps<Props>) => {
const [restProducts, setRestProducts] = useState<Map<number, DealProductSchema>>(new Map());
const [restProductsSelectData, setRestProductSelectData] = useState<ShippingProductOption[]>([]);
const [restProductsSelectData, setRestProductSelectData] = useState<ProductSchema[]>([]);
const getRestProductQuantity = () => {
if (form.values.productId) {
const restProduct = restProducts.get(Number(form.values.productId));
if (form.values.product) {
const restProduct = restProducts.get(form.values.product.id);
if (restProduct) {
return restProduct.quantity;
}
@@ -43,14 +44,19 @@ const ShippingProductModal = ({
return 10000;
};
const findProductById = (productId?: number | null) => {
const dealProduct = innerProps.deal.products.find(p => p.product.id === productId);
return dealProduct ? dealProduct.product : null;
};
const initialValues: ShippingModalForm = {
quantity: innerProps.shippingData.quantity ?? 0,
productId: innerProps.shippingData.productId,
product: findProductById(innerProps.shippingData.productId),
};
const form = useForm<ShippingModalForm>({
initialValues,
validate: {
productId: productId => !productId && "Необходимо выбрать товар",
product: product => !product && "Необходимо выбрать товар",
quantity: quantity => quantity > getRestProductQuantity() ? "Слишком много товара" :
quantity === 0 && "Слишком мало товара",
},
@@ -69,6 +75,7 @@ const ShippingProductModal = ({
const data = {
...innerProps.shippingData,
...form.values,
productId: form.values.product?.id,
} as CreateBoxInPalletSchema | CreateBoxInDealSchema | UpdateBoxSchema;
ShippingService.updateBox({
@@ -86,6 +93,7 @@ const ShippingProductModal = ({
const data = {
...innerProps.shippingData,
...form.values,
productId: form.values.product?.id,
} as CreateShippingProductSchema | UpdateShippingProductSchema;
ShippingService.updateShippingProduct({
@@ -108,7 +116,7 @@ const ShippingProductModal = ({
};
const getRestQuantityText = () => {
if (!form.values.productId) return;
if (!form.values.product) return;
const restQuantityInDeal = getRestProductQuantity();
const restQuantity = restQuantityInDeal - form.values.quantity;
@@ -125,12 +133,9 @@ const ShippingProductModal = ({
direction={"column"}
gap={rem(10)}
>
<Select
<ShippingProductSelect
{...form.getInputProps("product")}
data={restProductsSelectData}
label={"Товар"}
placeholder={"Выберите товар"}
{...form.getInputProps("productId")}
value={form.values.productId?.toString()}
/>
{getRestQuantityText()}

View File

@@ -1,13 +1,13 @@
import { CreateShippingProductSchema, UpdateBoxSchema, UpdateShippingProductSchema } from "../../../../../client";
import {
CreateShippingProductSchema,
ProductSchema,
UpdateBoxSchema,
UpdateShippingProductSchema,
} from "../../../../../client";
export type ShippingModalForm = {
quantity: number;
productId?: number | null;
}
export type ShippingProductOption = {
value: string;
label: string;
product?: ProductSchema | null;
}
export type ShippingData =

View File

@@ -1,4 +1,3 @@
import { ShippingProductOption } from "../types/ShippingProductData.tsx";
import { DealProductSchema, DealSchema, ProductSchema } from "../../../../../client";
type UnaccountedValues = {
@@ -61,11 +60,11 @@ const getRestProducts = ({
}
});
const restProductsSelectData: ShippingProductOption[] = [];
const restProductsSelectData: ProductSchema[] = [];
restProducts.forEach(
(restProduct, id) => {
restProductsSelectData.push({ value: String(id), label: restProduct.product.name });
(restProduct) => {
restProductsSelectData.push(restProduct.product);
},
);