This commit is contained in:
2024-04-12 07:35:41 +03:00
parent 9815ebbc3b
commit 2d1fdf1ad9
41 changed files with 1199 additions and 85 deletions

View File

@@ -1,12 +1,15 @@
import {Drawer, Text} from "@mantine/core";
import {Box, Drawer, rem, Tabs, Text} from "@mantine/core";
import {FC, useRef} from "react";
import DealServicesTable from "../../components/DealServicesTable/DealServicesTable.tsx";
import {useDealPageContext} from "../../contexts/DealPageContext.tsx";
import {DealService, DealServiceSchema} from "../../../../client";
import {DealProductSchema, DealService, DealServiceSchema} from "../../../../client";
import {notifications} from "../../../../shared/lib/notifications.ts";
import {modals} from "@mantine/modals";
import {BaseTableRef} from "../../../../components/BaseTable/BaseTable.tsx";
import DealProductsTable from "../../components/DealProductsTable/DealProductsTable.tsx";
import {IconBarcode, IconBox, IconCalendarUser, IconSettings} from "@tabler/icons-react";
import DealStatusChangeTable from "../../components/DealStatusChangeTable/DealStatusChangeTable.tsx";
import DealEditDrawerGeneralTab from "./tabs/DealEditDrawerGeneralTab.tsx";
const useDealServicesTableState = () => {
const {selectedDeal, setSelectedDeal} = useDealPageContext();
@@ -30,7 +33,6 @@ const useDealServicesTableState = () => {
.then(setSelectedDeal)
})
}
const onServiceDelete = (service: DealServiceSchema) => {
if (!selectedDeal) return;
modals.openConfirmModal({
@@ -68,7 +70,6 @@ const useDealServicesTableState = () => {
}
})
}
const onServiceCreate = (service: DealServiceSchema) => {
console.log('-------Drawer')
console.log(service);
@@ -88,7 +89,6 @@ const useDealServicesTableState = () => {
.then(setSelectedDeal)
})
}
const onsServiceMultipleDelete = (items: DealServiceSchema[]) => {
if (!selectedDeal) return;
modals.openConfirmModal({
@@ -152,27 +152,158 @@ const DealEditDrawerServicesTable = () => {
}
const useDealProductTableState = () => {
const {selectedDeal} = useDealPageContext();
const {selectedDeal, setSelectedDeal} = useDealPageContext();
const onProductUpdate = (product: DealProductSchema) => {
if (!selectedDeal) return;
DealService.updateDealProductQuantity({
requestBody: {
dealId: selectedDeal.id,
productId: product.product.id,
quantity: product.quantity
}
}).then(async ({ok, message}) => {
if (!ok) {
notifications.guess(ok, {message});
return;
}
await DealService.getDealById({dealId: selectedDeal.id})
.then(setSelectedDeal)
})
}
const onProductDelete = (product: DealProductSchema) => {
if (!selectedDeal) return;
modals.openConfirmModal({
title: "Удаление товара",
children: (
<>
<Text>
Вы уверены, что хотите удалить товар:
</Text>
<Text>
{product.product.name}?
</Text>
</>
),
onConfirm: () => {
DealService.deleteDealProduct({
requestBody: {
dealId: selectedDeal.id,
productId: product.product.id
}
}).then(async ({ok, message}) => {
if (!ok) {
notifications.guess(ok, {message});
return;
}
await DealService.getDealById({dealId: selectedDeal.id})
.then(setSelectedDeal)
})
},
labels: {
cancel: "Отмена",
confirm: "Удалить"
}
})
}
const onProductCreate = (product: DealProductSchema) => {
if (!selectedDeal) return;
DealService.addDealProduct({
requestBody: {
dealId: selectedDeal.id,
productId: product.product.id,
quantity: product.quantity
}
}).then(async ({ok, message}) => {
if (!ok) {
notifications.guess(ok, {message});
return;
}
await DealService.getDealById({dealId: selectedDeal.id})
.then(setSelectedDeal)
})
}
const onProductMultipleDelete = (items: DealProductSchema[]) => {
if (!selectedDeal) return;
modals.openConfirmModal({
title: "Удаление товаров",
children: (
<>
<Text>
Вы уверены, что хотите удалить выбранные товары?
</Text>
</>
),
onConfirm: () => {
DealService.deleteMultipleDealProducts({
requestBody: {
dealId: selectedDeal.id,
productIds: items.map(item => item.product.id)
}
}).then(async ({ok, message}) => {
if (!ok) {
notifications.guess(ok, {message});
return;
}
await DealService.getDealById({dealId: selectedDeal.id})
.then(setSelectedDeal)
})
},
labels: {
cancel: "Отмена",
confirm: "Удалить"
}
})
}
return {
clientId: selectedDeal?.clientId || -1,
products: selectedDeal?.products || []
products: selectedDeal?.products || [],
onProductUpdate,
onProductDelete,
onProductCreate,
onProductMultipleDelete
}
}
const DealEditDrawerProductsTable = () => {
const {
products,
clientId
clientId,
onProductUpdate,
onProductDelete,
onProductCreate,
onProductMultipleDelete,
} = useDealProductTableState();
return (
<DealProductsTable
clientId={clientId}
items={products}
onChange={onProductUpdate}
onMultipleDelete={onProductMultipleDelete}
onDelete={onProductDelete}
onCreate={onProductCreate}
/>
)
}
const useDealStatusChangeState = () => {
const {selectedDeal} = useDealPageContext();
return {
statusHistory: selectedDeal?.statusHistory || []
}
}
const DealEditDrawerStatusChangeTable = () => {
const {statusHistory} = useDealStatusChangeState();
return (
<DealStatusChangeTable
items={statusHistory}
/>)
}
const useDealEditDrawerState = () => {
const {selectedDeal, setSelectedDeal} = useDealPageContext();
return {
@@ -189,9 +320,55 @@ const DealEditDrawer: FC = () => {
size={"95%"}
position={"right"}
onClose={onClose}
opened={isVisible}>
<DealEditDrawerServicesTable/>
<DealEditDrawerProductsTable/>
removeScrollProps={{allowPinchZoom: true}}
withCloseButton={false}
opened={isVisible}
styles={{body: {height: '100%'}}}
>
<Tabs
defaultValue={"general"}
h={'100%'}
variant={"outline"}
orientation={"vertical"}>
<Tabs.List
>
<Tabs.Tab value={"general"} leftSection={<IconSettings/>}>
Общее
</Tabs.Tab>
<Tabs.Tab value={"history"} leftSection={<IconCalendarUser/>}>
История
</Tabs.Tab>
<Tabs.Tab value={"services"} leftSection={<IconBox/>}>
Услуги
</Tabs.Tab>
<Tabs.Tab value={"products"} leftSection={<IconBarcode/>}>
Товары
</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value={"general"}>
<Box h={"100%"} w={"100%"} p={rem(10)}>
<DealEditDrawerGeneralTab/>
</Box>
</Tabs.Panel>
<Tabs.Panel value={"history"}>
<Box p={rem(10)}>
<DealEditDrawerStatusChangeTable/>
</Box>
</Tabs.Panel>
<Tabs.Panel value={"services"}>
<Box p={rem(10)}>
<DealEditDrawerServicesTable/>
</Box>
</Tabs.Panel>
<Tabs.Panel value={"products"}>
<Box p={rem(10)}>
<DealEditDrawerProductsTable/>
</Box>
</Tabs.Panel>
</Tabs>
</Drawer>
);
}

View File

@@ -0,0 +1,148 @@
import {FC} from "react";
import {useDealPageContext} from "../../../contexts/DealPageContext.tsx";
import {Button, Checkbox, Fieldset, Flex, Group, rem, TextInput} from "@mantine/core";
import {useForm} from "@mantine/form";
import {ClientService, DealSchema, DealService} from "../../../../../client";
import {DealStatus, DealStatusDictionary} from "../../../../../shared/enums/DealStatus.ts";
import {isEqual} from "lodash";
import {notifications} from "../../../../../shared/lib/notifications.ts";
import {useQueryClient} from "@tanstack/react-query";
type Props = {
deal: DealSchema
}
type FormType = Omit<DealSchema, 'statusHistory' | 'services' | 'products'>
const Content: FC<Props> = ({deal}) => {
const {setSelectedDeal} = useDealPageContext();
const queryClient = useQueryClient();
const initialValues: FormType = deal;
const form = useForm<FormType>(
{
initialValues: initialValues,
validate: {
name: (value: string) => value.length > 0 ? null : 'Название сделки не может быть пустым'
}
}
)
const updateDealInfo = async (values: FormType) => {
return DealService.updateDealGeneralInfo({
requestBody: {
dealId: deal.id,
data: values
}
}).then(({ok, message}) => {
notifications.guess(ok, {message});
if (!ok) return;
DealService.getDealById({dealId: deal.id})
.then((data) => {
setSelectedDeal(data);
form.setInitialValues(data);
queryClient.invalidateQueries({
queryKey: ['getDealSummaries']
})
})
});
}
const updateClientInfo = async (values: FormType) => {
return ClientService.updateClient({
requestBody: {
data: values.client
}
}).then(({ok, message}) =>
notifications.guess(ok, {message}));
}
const handleSubmit = async (values: FormType) => {
// Updating client info if there changes
if (!isEqual(values.client, deal.client)) {
await updateClientInfo(values);
}
// updating deal info
await updateDealInfo(values);
}
return (
<form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
<Fieldset legend={"Общие параметры"}>
<Flex direction={"column"} gap={rem(10)}>
<TextInput
placeholder={"Название сделки"}
label={"Название сделки"}
{...form.getInputProps('name')}
/>
<TextInput
disabled
placeholder={"Дата создания"}
label={"Дата создания"}
value={new Date(deal.createdAt).toLocaleString('ru-RU')}
/>
<TextInput
disabled
placeholder={"Текущий статус"}
label={"Текущий статус"}
value={DealStatusDictionary[deal.currentStatus as DealStatus]}/>
<Checkbox
label={"Сделка завершена"}
{...form.getInputProps('isCompleted')}
/>
<Checkbox
label={"Сделка удалена"}
{...form.getInputProps('isDeleted')}
/>
</Flex>
</Fieldset>
<Fieldset legend={"Клиент"}>
<TextInput
disabled
placeholder={"Название"}
label={"Название"}
value={deal.client.name}
/>
<TextInput
placeholder={"Введите телефон"}
label={"Телефон клиента"}
{...form.getInputProps('client.details.phoneNumber')}
/>
<TextInput
placeholder={"Введите email"}
label={"Email"}
{...form.getInputProps('client.details.email')}
/>
<TextInput
placeholder={"Введите адрес"}
label={"Адрес"}
{...form.getInputProps('client.details.address')}
/>
<TextInput
placeholder={"Введите ИНН"}
label={"ИНН"}
{...form.getInputProps('client.details.inn')}
/>
</Fieldset>
<Group justify={"flex-end"} mt={"md"}>
<Button
color={"red"}
type={"reset"}
disabled={isEqual(initialValues, form.values)}
onClick={() => form.reset()}
>Отменить изменения</Button>
<Button
variant={"default"}
type={"submit"}
disabled={isEqual(initialValues, form.values)}
>Сохранить изменения</Button>
</Group>
</form>
)
}
const DealEditDrawerGeneralTab: FC = () => {
const {selectedDeal} = useDealPageContext();
if (!selectedDeal) return <>No deal selected</>;
return (
<Content deal={selectedDeal}/>
);
}
export default DealEditDrawerGeneralTab;