feat: price by category

This commit is contained in:
2024-09-27 04:41:18 +03:00
parent f30c55456c
commit c5f839d9ef
44 changed files with 1316 additions and 681 deletions

View File

@@ -1,99 +1,108 @@
import {Button, rem, Textarea, TextInput} from "@mantine/core";
import {QuickDeal} from "../../../types/QuickDeal.ts";
import {FC} from "react";
import {useForm} from "@mantine/form";
import styles from './CreateDealForm.module.css';
import { Button, rem, Textarea, TextInput } from "@mantine/core";
import { QuickDeal } from "../../../types/QuickDeal.ts";
import { FC } from "react";
import { useForm } from "@mantine/form";
import styles from "./CreateDealForm.module.css";
import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx";
import {DateTimePicker} from "@mantine/dates";
import { DateTimePicker } from "@mantine/dates";
import ShippingWarehouseAutocomplete
from "../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
import BaseMarketplaceSelect from "../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
import ServicePriceCategorySelect from "../../Selects/ServicePriceCategorySelect/ServicePriceCategorySelect.tsx";
type Props = {
onSubmit: (quickDeal: QuickDeal) => void
onCancel: () => void;
}
const CreateDealFrom: FC<Props> = ({onSubmit, onCancel}) => {
const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
const form = useForm<QuickDeal>({
initialValues: {
name: '',
clientName: '',
clientAddress: '',
comment: '',
name: "",
clientName: "",
clientAddress: "",
comment: "",
acceptanceDate: new Date(),
shippingWarehouse: '',
shippingWarehouse: "",
baseMarketplace: {
key: "",
iconUrl: "",
name: ""
}
}
name: "",
},
},
});
return (
<form
style={{width: '100%'}}
style={{ width: "100%" }}
onSubmit={form.onSubmit((values) => onSubmit(values))}
>
<div style={{
display: 'flex',
flexDirection: 'column',
width: '100%',
display: "flex",
flexDirection: "column",
width: "100%",
gap: rem(10),
padding: rem(10)
padding: rem(10),
}}>
<div className={styles['inputs']}>
<div className={styles["inputs"]}>
<TextInput
placeholder={'Название сделки'}
{...form.getInputProps('name')}
placeholder={"Название сделки"}
{...form.getInputProps("name")}
/>
</div>
<div className={styles['inputs']}>
<div className={styles["inputs"]}>
<ClientAutocomplete
nameRestProps={form.getInputProps('clientName')}
nameRestProps={form.getInputProps("clientName")}
/>
</div>
<div className={styles['inputs']}>
<div className={styles["inputs"]}>
<BaseMarketplaceSelect
rightSection={<></>}
placeholder={"Базовый маркетплейс"}
{...form.getInputProps("baseMarketplace")}
/>
<ShippingWarehouseAutocomplete
{...form.getInputProps('shippingWarehouse')}
placeholder={'Склад отгрузки'}
{...form.getInputProps("shippingWarehouse")}
placeholder={"Склад отгрузки"}
/>
</div>
<div className={styles["inputs"]}>
<ServicePriceCategorySelect
rightSection={<></>}
placeholder={"Выберите категорию"}
{...form.getInputProps("category")}
/>
</div>
<div className={styles['inputs']}>
<div className={styles["inputs"]}>
<Textarea
autosize
placeholder={'Комментарий'}
placeholder={"Комментарий"}
minRows={2}
maxRows={4}
{...form.getInputProps('comment')}
{...form.getInputProps("comment")}
/>
</div>
<div className={styles['inputs']}>
<div className={styles["inputs"]}>
<DateTimePicker
placeholder={'Дата приемки'}
{...form.getInputProps('acceptanceDate')}
placeholder={"Дата приемки"}
{...form.getInputProps("acceptanceDate")}
/>
</div>
<div className={styles['buttons']}>
<div className={styles["buttons"]}>
<Button
type={'submit'}
type={"submit"}
>Добавить</Button>
<Button
variant={'outline'}
variant={"outline"}
onClick={() => onCancel()}
>Отменить</Button>
</div>
</div>
</form>
)
}
);
};
export default CreateDealFrom;

View File

@@ -0,0 +1,17 @@
import ObjectSelect, { ObjectSelectProps } from "../../ObjectSelect/ObjectSelect.tsx";
import { ServicePriceCategorySchema } from "../../../client";
import useServicePriceCategoriesList from "../../../pages/ServicesPage/hooks/useServicePriceCategoriesList.tsx";
type Props = Omit<ObjectSelectProps<ServicePriceCategorySchema>, "data">
const ServicePriceCategorySelect = (props: Props) => {
const { objects } = useServicePriceCategoriesList();
return (
<ObjectSelect
{...props}
data={objects}
/>
);
};
export default ServicePriceCategorySelect;

View File

@@ -1,11 +1,11 @@
import {ObjectSelectProps} from "../ObjectSelect/ObjectSelect.tsx";
import {ServiceSchema} from "../../client";
import {Flex, FlexProps, NumberInput, NumberInputProps, rem} from "@mantine/core";
import {FC, useEffect, useRef, useState} from "react";
import { ObjectSelectProps } from "../ObjectSelect/ObjectSelect.tsx";
import { ServicePriceCategorySchema, ServiceSchema } from "../../client";
import { Flex, FlexProps, NumberInput, NumberInputProps, rem } from "@mantine/core";
import { FC, useEffect, useRef, useState } from "react";
import ServiceSelectNew from "../Selects/ServiceSelectNew/ServiceSelectNew.tsx";
import {ServiceType} from "../../shared/enums/ServiceType.ts";
import { ServiceType } from "../../shared/enums/ServiceType.ts";
type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, 'data'>;
type ServiceProps = Omit<ObjectSelectProps<ServiceSchema>, "data">;
type PriceProps = NumberInputProps;
type Props = {
@@ -15,6 +15,7 @@ type Props = {
containerProps: FlexProps,
filterType?: ServiceType,
lockOnEdit?: boolean
category?: ServicePriceCategorySchema
}
const ServiceWithPriceInput: FC<Props> = ({
serviceProps,
@@ -22,10 +23,11 @@ const ServiceWithPriceInput: FC<Props> = ({
quantity,
containerProps,
filterType = ServiceType.PRODUCT_SERVICE,
lockOnEdit = true
lockOnEdit = true,
category,
}) => {
const [price, setPrice] = useState<number | undefined>(
typeof priceProps.value === 'number' ? priceProps.value : undefined);
typeof priceProps.value === "number" ? priceProps.value : undefined);
const [service, setService] = useState<ServiceSchema | undefined>(serviceProps.value);
const isFirstRender = useRef(true);
const setPriceBasedOnQuantity = (): boolean => {
@@ -35,29 +37,40 @@ const ServiceWithPriceInput: FC<Props> = ({
setPrice(range.price);
return true;
}
};
const setPriceBasedOnCategory = () => {
if (!category || !service) return false;
const categoryPrice = service.categoryPrices.find(categoryPrice => categoryPrice.category.id === category.id);
if (!categoryPrice) return false;
setPrice(categoryPrice.price);
return true;
};
const setPriceBasedOnService = () => {
if (!service) return;
// if category is set, we should not set price based on service
if (setPriceBasedOnCategory()) return;
if (setPriceBasedOnQuantity()) return;
setPrice(service.price);
}
};
const onServiceManualChange = (service: ServiceSchema) => {
setService(service);
}
};
const onPriceManualChange = (value: number | string) => {
if (typeof value !== 'number') return;
if (typeof value !== "number") return;
setPrice(value);
}
};
useEffect(() => {
if (isFirstRender.current && lockOnEdit) return;
// we need to set price based on quantity only if category is not set, because category has higher priority
if (category) return;
setPriceBasedOnQuantity();
}, [quantity]);
useEffect(() => {
if (isFirstRender.current && lockOnEdit) return;
if (!priceProps.onChange || typeof price === 'undefined') return;
if (!priceProps.onChange || typeof price === "undefined") return;
priceProps.onChange(price);
}, [price]);
@@ -97,7 +110,7 @@ const ServiceWithPriceInput: FC<Props> = ({
/>
</Flex>
)
}
);
};
export default ServiceWithPriceInput;