feat: price by category
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
import {Box, Drawer, rem, Tabs, Text} from "@mantine/core";
|
||||
import {FC, useEffect, useRef} from "react";
|
||||
import { Box, Drawer, rem, Tabs, Text } from "@mantine/core";
|
||||
import { FC, useEffect, useRef } from "react";
|
||||
import DealServicesTable from "../../components/DealServicesTable/DealServicesTable.tsx";
|
||||
import {useDealPageContext} from "../../contexts/DealPageContext.tsx";
|
||||
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 { useDealPageContext } from "../../contexts/DealPageContext.tsx";
|
||||
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 {IconBox, IconCalendarUser, IconSettings} from "@tabler/icons-react";
|
||||
import { IconBox, IconCalendarUser, IconSettings } from "@tabler/icons-react";
|
||||
import DealStatusChangeTable from "../../components/DealStatusChangeTable/DealStatusChangeTable.tsx";
|
||||
import DealEditDrawerGeneralTab from "./tabs/DealEditDrawerGeneralTab.tsx";
|
||||
import {useQueryClient} from "@tanstack/react-query";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import ProductAndServiceTab from "../../tabs/ProductAndServiceTab/ProductAndServiceTab.tsx";
|
||||
import {motion} from "framer-motion";
|
||||
import { motion } from "framer-motion";
|
||||
// import styles from './DealEditDrawer.module.css';
|
||||
|
||||
const useDealServicesTableState = () => {
|
||||
const {selectedDeal, setSelectedDeal} = useDealPageContext();
|
||||
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
||||
const tableRef = useRef<BaseTableRef<DealServiceSchema>>(null);
|
||||
|
||||
const onServiceUpdate = (service: DealServiceSchema) => {
|
||||
@@ -24,18 +24,18 @@ const useDealServicesTableState = () => {
|
||||
DealService.updateDealService({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
service
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
service,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
}
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
};
|
||||
const onServiceDelete = (service: DealServiceSchema) => {
|
||||
if (!selectedDeal) return;
|
||||
modals.openConfirmModal({
|
||||
@@ -56,23 +56,23 @@ const useDealServicesTableState = () => {
|
||||
DealService.deleteDealService({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
serviceId: service.service.id
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
serviceId: service.service.id,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
cancel: "Отмена",
|
||||
confirm: "Удалить"
|
||||
}
|
||||
})
|
||||
}
|
||||
confirm: "Удалить",
|
||||
},
|
||||
});
|
||||
};
|
||||
const onServiceCreate = (service: DealServiceSchema) => {
|
||||
if (!selectedDeal) return;
|
||||
DealService.addDealService({
|
||||
@@ -80,17 +80,17 @@ const useDealServicesTableState = () => {
|
||||
dealId: selectedDeal.id,
|
||||
serviceId: service.service.id,
|
||||
quantity: service.quantity,
|
||||
price: service.price
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
price: service.price,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
}
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
};
|
||||
const onsServiceMultipleDelete = (items: DealServiceSchema[]) => {
|
||||
if (!selectedDeal) return;
|
||||
modals.openConfirmModal({
|
||||
@@ -106,23 +106,23 @@ const useDealServicesTableState = () => {
|
||||
DealService.deleteMultipleDealServices({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
serviceIds: items.map(item => item.service.id)
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
serviceIds: items.map(item => item.service.id),
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
cancel: "Отмена",
|
||||
confirm: "Удалить"
|
||||
}
|
||||
})
|
||||
}
|
||||
confirm: "Удалить",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
onServiceUpdate,
|
||||
@@ -130,9 +130,9 @@ const useDealServicesTableState = () => {
|
||||
onServiceCreate,
|
||||
onsServiceMultipleDelete,
|
||||
tableRef,
|
||||
services: selectedDeal?.services || []
|
||||
}
|
||||
}
|
||||
services: selectedDeal?.services || [],
|
||||
};
|
||||
};
|
||||
const DealEditDrawerServicesTable = () => {
|
||||
const {
|
||||
services,
|
||||
@@ -140,7 +140,7 @@ const DealEditDrawerServicesTable = () => {
|
||||
onServiceCreate,
|
||||
onServiceUpdate,
|
||||
onServiceDelete,
|
||||
onsServiceMultipleDelete
|
||||
onsServiceMultipleDelete,
|
||||
} = useDealServicesTableState();
|
||||
|
||||
return (<DealServicesTable
|
||||
@@ -150,26 +150,26 @@ const DealEditDrawerServicesTable = () => {
|
||||
onDelete={onServiceDelete}
|
||||
onCreate={onServiceCreate}
|
||||
onMultipleDelete={onsServiceMultipleDelete}
|
||||
/>)
|
||||
}
|
||||
/>);
|
||||
};
|
||||
|
||||
const useDealProductTableState = () => {
|
||||
const {selectedDeal, setSelectedDeal} = useDealPageContext();
|
||||
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
||||
|
||||
const onProductUpdate = (product: DealProductSchema) => {
|
||||
if (!selectedDeal) return;
|
||||
DealService.updateDealProduct({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
product: product
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
notifications.guess(ok, {message});
|
||||
product: product,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
notifications.guess(ok, { message });
|
||||
if (!ok) return;
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
}
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
};
|
||||
const onProductDelete = (product: DealProductSchema) => {
|
||||
if (!selectedDeal) return;
|
||||
modals.openConfirmModal({
|
||||
@@ -190,39 +190,39 @@ const useDealProductTableState = () => {
|
||||
DealService.deleteDealProduct({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
productId: product.product.id
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
productId: product.product.id,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
cancel: "Отмена",
|
||||
confirm: "Удалить"
|
||||
}
|
||||
})
|
||||
}
|
||||
confirm: "Удалить",
|
||||
},
|
||||
});
|
||||
};
|
||||
const onProductCreate = (product: DealProductSchema) => {
|
||||
if (!selectedDeal) return;
|
||||
DealService.addDealProduct({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
product: product
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
product: product,
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
}
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
};
|
||||
const onProductMultipleDelete = (items: DealProductSchema[]) => {
|
||||
if (!selectedDeal) return;
|
||||
modals.openConfirmModal({
|
||||
@@ -238,32 +238,32 @@ const useDealProductTableState = () => {
|
||||
DealService.deleteMultipleDealProducts({
|
||||
requestBody: {
|
||||
dealId: selectedDeal.id,
|
||||
productIds: items.map(item => item.product.id)
|
||||
}
|
||||
}).then(async ({ok, message}) => {
|
||||
productIds: items.map(item => item.product.id),
|
||||
},
|
||||
}).then(async ({ ok, message }) => {
|
||||
if (!ok) {
|
||||
notifications.guess(ok, {message});
|
||||
notifications.guess(ok, { message });
|
||||
return;
|
||||
}
|
||||
await DealService.getDealById({dealId: selectedDeal.id})
|
||||
.then(setSelectedDeal)
|
||||
})
|
||||
await DealService.getDealById({ dealId: selectedDeal.id })
|
||||
.then(setSelectedDeal);
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
cancel: "Отмена",
|
||||
confirm: "Удалить"
|
||||
}
|
||||
})
|
||||
}
|
||||
confirm: "Удалить",
|
||||
},
|
||||
});
|
||||
};
|
||||
return {
|
||||
clientId: selectedDeal?.clientId || -1,
|
||||
products: selectedDeal?.products || [],
|
||||
onProductUpdate,
|
||||
onProductDelete,
|
||||
onProductCreate,
|
||||
onProductMultipleDelete
|
||||
}
|
||||
}
|
||||
onProductMultipleDelete,
|
||||
};
|
||||
};
|
||||
const DealEditDrawerProductsTable = () => {
|
||||
const {
|
||||
products,
|
||||
@@ -283,79 +283,86 @@ const DealEditDrawerProductsTable = () => {
|
||||
onCreate={onProductCreate}
|
||||
|
||||
/>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const useDealStatusChangeState = () => {
|
||||
const {selectedDeal} = useDealPageContext();
|
||||
const { selectedDeal } = useDealPageContext();
|
||||
return {
|
||||
statusHistory: selectedDeal?.statusHistory || []
|
||||
}
|
||||
}
|
||||
statusHistory: selectedDeal?.statusHistory || [],
|
||||
};
|
||||
};
|
||||
const DealEditDrawerStatusChangeTable = () => {
|
||||
const {statusHistory} = useDealStatusChangeState();
|
||||
const { statusHistory } = useDealStatusChangeState();
|
||||
|
||||
return (
|
||||
<DealStatusChangeTable
|
||||
items={statusHistory}
|
||||
/>)
|
||||
}
|
||||
/>);
|
||||
};
|
||||
|
||||
const useDealEditDrawerState = () => {
|
||||
const {selectedDeal, setSelectedDeal} = useDealPageContext();
|
||||
const { selectedDeal, setSelectedDeal } = useDealPageContext();
|
||||
return {
|
||||
isVisible: selectedDeal !== undefined,
|
||||
onClose: () => setSelectedDeal(undefined)
|
||||
}
|
||||
}
|
||||
onClose: () => setSelectedDeal(undefined),
|
||||
};
|
||||
};
|
||||
|
||||
const DealEditDrawer: FC = () => {
|
||||
const {isVisible, onClose} = useDealEditDrawerState();
|
||||
const { isVisible, onClose } = useDealEditDrawerState();
|
||||
const queryClient = useQueryClient();
|
||||
useEffect(() => {
|
||||
if (isVisible) return;
|
||||
queryClient.invalidateQueries({queryKey: ["getDealSummaries"]})
|
||||
queryClient.invalidateQueries({ queryKey: ["getDealSummaries"] });
|
||||
}, [isVisible]);
|
||||
return (
|
||||
<Drawer
|
||||
size={"calc(100vw - 150px)"}
|
||||
position={"right"}
|
||||
onClose={onClose}
|
||||
removeScrollProps={{allowPinchZoom: true}}
|
||||
removeScrollProps={{ allowPinchZoom: true }}
|
||||
withCloseButton={false}
|
||||
opened={isVisible}
|
||||
styles={{body: {height: '100%'}}}
|
||||
styles={{
|
||||
body: {
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column", gap: rem(10),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tabs
|
||||
defaultValue={"general"}
|
||||
h={'100%'}
|
||||
flex={1}
|
||||
variant={"outline"}
|
||||
orientation={"vertical"}
|
||||
keepMounted={false}
|
||||
|
||||
>
|
||||
|
||||
<Tabs.List
|
||||
>
|
||||
<Tabs.Tab value={"general"} leftSection={<IconSettings/>}>
|
||||
<Tabs.Tab value={"general"} leftSection={<IconSettings />}>
|
||||
Общее
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value={"history"} leftSection={<IconCalendarUser/>}>
|
||||
<Tabs.Tab value={"history"} leftSection={<IconCalendarUser />}>
|
||||
История
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab value={"servicesAndProducts"} leftSection={<IconBox/>}>
|
||||
<Tabs.Tab value={"servicesAndProducts"} leftSection={<IconBox />}>
|
||||
Товары и услуги
|
||||
</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Tabs.Panel value={"general"}>
|
||||
<motion.div
|
||||
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
|
||||
<Box h={"100%"} w={"100%"} p={rem(10)}>
|
||||
<DealEditDrawerGeneralTab/>
|
||||
<DealEditDrawerGeneralTab />
|
||||
|
||||
</Box>
|
||||
</motion.div>
|
||||
@@ -364,40 +371,40 @@ const DealEditDrawer: FC = () => {
|
||||
<Tabs.Panel value={"history"}>
|
||||
<motion.div
|
||||
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Box p={rem(10)}>
|
||||
<DealEditDrawerStatusChangeTable/>
|
||||
<DealEditDrawerStatusChangeTable />
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value={"servicesAndProducts"}>
|
||||
<motion.div
|
||||
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Box p={rem(10)}>
|
||||
<ProductAndServiceTab/>
|
||||
<ProductAndServiceTab />
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value={"services"}>
|
||||
<Box p={rem(10)}>
|
||||
<DealEditDrawerServicesTable/>
|
||||
<DealEditDrawerServicesTable />
|
||||
</Box>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value={"products"}>
|
||||
<Box p={rem(10)}>
|
||||
<DealEditDrawerProductsTable/>
|
||||
<DealEditDrawerProductsTable />
|
||||
</Box>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default DealEditDrawer;
|
||||
@@ -103,7 +103,7 @@ const Content: FC<Props> = ({ deal }) => {
|
||||
};
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
|
||||
<Flex direction={"column"}>
|
||||
<Flex direction={"column"} justify={"space-between"} h={"100%"}>
|
||||
<Fieldset legend={`Общие параметры [ID: ${deal.id}]`}>
|
||||
<Flex direction={"column"} gap={rem(10)}>
|
||||
<TextInput
|
||||
@@ -122,6 +122,15 @@ const Content: FC<Props> = ({ deal }) => {
|
||||
placeholder={"Текущий статус"}
|
||||
label={"Текущий статус"}
|
||||
value={DealStatusDictionary[deal.currentStatus as DealStatus]} />
|
||||
{deal.category && (
|
||||
<TextInput
|
||||
disabled
|
||||
placeholder={"Категория"}
|
||||
label={"Категория"}
|
||||
value={deal.category.name}
|
||||
|
||||
/>
|
||||
)}
|
||||
<Textarea
|
||||
label={"Коментарий к сделке"}
|
||||
placeholder={"Введите коментарий к сделке"}
|
||||
@@ -141,34 +150,6 @@ const Content: FC<Props> = ({ deal }) => {
|
||||
/>
|
||||
</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.telegram")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите ИНН"}
|
||||
label={"ИНН"}
|
||||
{...form.getInputProps("client.details.inn")}
|
||||
/>
|
||||
</Fieldset>
|
||||
<Flex mt={"md"} gap={rem(10)} align={"center"} justify={"flex-end"}>
|
||||
<Flex align={"center"} gap={rem(10)} justify={"center"}>
|
||||
|
||||
@@ -199,10 +180,7 @@ const Content: FC<Props> = ({ deal }) => {
|
||||
:
|
||||
<ButtonCopyControlled
|
||||
onCopyClick={() => {
|
||||
// get current datetime for filename, replaced dots with _
|
||||
const date = getCurrentDateTimeForFilename();
|
||||
|
||||
|
||||
FileSaver.saveAs(`${import.meta.env.VITE_API_URL}/deal/document/${deal.id}`,
|
||||
`bill_${deal.id}_${date}.pdf`);
|
||||
}}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import {ContextModalProps} from "@mantine/modals";
|
||||
import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||
import {DealProductSchema, DealProductServiceSchema} from "../../../client";
|
||||
import {useForm} from "@mantine/form";
|
||||
import {Fieldset, NumberInput} from "@mantine/core";
|
||||
import { ContextModalProps } from "@mantine/modals";
|
||||
import BaseFormModal, { CreateEditFormProps } from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||
import { DealProductSchema, DealProductServiceSchema } from "../../../client";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { NumberInput } from "@mantine/core";
|
||||
import ProductSelect from "../../../components/ProductSelect/ProductSelect.tsx";
|
||||
import DealProductServiceTable from "../components/DealProductsTable/DealProductServiceTable.tsx";
|
||||
import {omit} from "lodash";
|
||||
import {BaseFormInputProps} from "../../../types/utils.ts";
|
||||
import { omit } from "lodash";
|
||||
|
||||
type RestProps = {
|
||||
clientId: number;
|
||||
@@ -65,13 +63,13 @@ const AddDealProductModal = ({
|
||||
min={1}
|
||||
{...form.getInputProps('quantity')}
|
||||
/>
|
||||
<Fieldset legend={'Услуги'}>
|
||||
<DealProductServiceTable
|
||||
quantity={form.values.quantity || 1}
|
||||
{...form.getInputProps('services') as
|
||||
BaseFormInputProps<DealProductServiceSchema[]>}
|
||||
/>
|
||||
</Fieldset>
|
||||
{/*<Fieldset legend={'Услуги'}>*/}
|
||||
{/* <DealProductServiceTable*/}
|
||||
{/* quantity={form.values.quantity || 1}*/}
|
||||
{/* {...form.getInputProps('services') as*/}
|
||||
{/* BaseFormInputProps<DealProductServiceSchema[]>}*/}
|
||||
{/* />*/}
|
||||
{/*</Fieldset>*/}
|
||||
|
||||
</>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {ContextModalProps} from "@mantine/modals";
|
||||
import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||
import {DealServiceSchema} from "../../../client";
|
||||
import { DealServiceSchema, ServicePriceCategorySchema } from "../../../client";
|
||||
import {useForm} from "@mantine/form";
|
||||
import {ComboboxItem, ComboboxItemGroup, NumberInput, OptionsFilter} from "@mantine/core";
|
||||
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
||||
@@ -10,6 +10,7 @@ import {RootState} from "../../../redux/store.ts";
|
||||
|
||||
type RestProps = {
|
||||
serviceIds?: number[];
|
||||
category?: ServicePriceCategorySchema;
|
||||
}
|
||||
type Props = CreateEditFormProps<Partial<DealServiceSchema>> & RestProps;
|
||||
const AddDealServiceModal = ({
|
||||
@@ -18,7 +19,7 @@ const AddDealServiceModal = ({
|
||||
innerProps
|
||||
}: ContextModalProps<Props>) => {
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
console.log(innerProps.category)
|
||||
const isEditing = 'element' in innerProps;
|
||||
const form = useForm<Partial<DealServiceSchema>>({
|
||||
initialValues: isEditing ? innerProps.element : {
|
||||
@@ -54,6 +55,7 @@ const AddDealServiceModal = ({
|
||||
<BaseFormModal.Body>
|
||||
<>
|
||||
<ServiceWithPriceInput
|
||||
category={innerProps.category}
|
||||
serviceProps={{
|
||||
...form.getInputProps('service'),
|
||||
label: "Услуга",
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
import BaseFormModal, {CreateEditFormProps} from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||
import {DealProductServiceSchema, ServiceSchema} from "../../../client";
|
||||
import {ContextModalProps} from "@mantine/modals";
|
||||
import {useForm, UseFormReturnType} from "@mantine/form";
|
||||
import {isNil, isNumber} from "lodash";
|
||||
import BaseFormModal, { CreateEditFormProps } from "../../ClientsPage/modals/BaseFormModal/BaseFormModal.tsx";
|
||||
import { DealProductServiceSchema, ServicePriceCategorySchema, ServiceSchema } from "../../../client";
|
||||
import { ContextModalProps } from "@mantine/modals";
|
||||
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||
import { isNil, isNumber } from "lodash";
|
||||
import ServiceWithPriceInput from "../../../components/ServiceWithPriceInput/ServiceWithPriceInput.tsx";
|
||||
import {Flex} from "@mantine/core";
|
||||
import {ServiceType} from "../../../shared/enums/ServiceType.ts";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "../../../redux/store.ts";
|
||||
import { Flex } from "@mantine/core";
|
||||
import { ServiceType } from "../../../shared/enums/ServiceType.ts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../redux/store.ts";
|
||||
|
||||
type RestProps = {
|
||||
quantity: number;
|
||||
serviceIds: number[];
|
||||
category?: ServicePriceCategorySchema;
|
||||
}
|
||||
type Props = CreateEditFormProps<DealProductServiceSchema> & RestProps;
|
||||
|
||||
const ProductServiceFormModal = ({
|
||||
context,
|
||||
id, innerProps
|
||||
id, innerProps,
|
||||
}: ContextModalProps<Props>) => {
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
const isEditing = 'onChange' in innerProps;
|
||||
const isEditing = "onChange" in innerProps;
|
||||
const initialValues: Partial<DealProductServiceSchema> = isEditing ? innerProps.element : {
|
||||
service: undefined,
|
||||
price: undefined,
|
||||
employees: []
|
||||
}
|
||||
employees: [],
|
||||
};
|
||||
const form = useForm<Partial<DealProductServiceSchema>>({
|
||||
initialValues,
|
||||
validate: {
|
||||
service: (service?: ServiceSchema) => isNil(service) || service.id < 0 ? 'Укажите услугу' : null,
|
||||
price: (price?: number) => !isNumber(price) || price < 0 ? 'Укажите цену' : null
|
||||
}
|
||||
})
|
||||
service: (service?: ServiceSchema) => isNil(service) || service.id < 0 ? "Укажите услугу" : null,
|
||||
price: (price?: number) => !isNumber(price) || price < 0 ? "Укажите цену" : null,
|
||||
},
|
||||
});
|
||||
const onClose = () => {
|
||||
context.closeContextModal(id);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<BaseFormModal
|
||||
{...innerProps}
|
||||
@@ -49,25 +50,26 @@ const ProductServiceFormModal = ({
|
||||
<Flex w={"100%"}>
|
||||
|
||||
<ServiceWithPriceInput
|
||||
category={innerProps.category}
|
||||
serviceProps={{
|
||||
...form.getInputProps('service'),
|
||||
...form.getInputProps("service"),
|
||||
label: "Услуга",
|
||||
placeholder: "Выберите услугу",
|
||||
disabled: isEditing,
|
||||
filterBy: (item) => !innerProps.serviceIds.includes(item.id) || isEditing,
|
||||
style: {width: "100%"}
|
||||
style: { width: "100%" },
|
||||
}}
|
||||
priceProps={{
|
||||
...form.getInputProps('price'),
|
||||
...form.getInputProps("price"),
|
||||
label: "Цена",
|
||||
placeholder: "Введите цену",
|
||||
style: {width: "100%"},
|
||||
disabled: authState.isGuest
|
||||
style: { width: "100%" },
|
||||
disabled: authState.isGuest,
|
||||
}}
|
||||
filterType={ServiceType.PRODUCT_SERVICE}
|
||||
containerProps={{
|
||||
direction: "column",
|
||||
style: {width: "100%"}
|
||||
style: { width: "100%" },
|
||||
|
||||
}}
|
||||
lockOnEdit={isEditing}
|
||||
@@ -79,6 +81,6 @@ const ProductServiceFormModal = ({
|
||||
</BaseFormModal.Body>
|
||||
</BaseFormModal>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export default ProductServiceFormModal;
|
||||
@@ -1,24 +1,24 @@
|
||||
import {CRUDTableProps} from "../../../../../../types/CRUDTable.tsx";
|
||||
import {DealServiceSchema, GetServiceKitSchema, UserSchema} from "../../../../../../client";
|
||||
import {FC, useState} from "react";
|
||||
import {ActionIcon, Button, Flex, Modal, NumberInput, rem, Text, Title, Tooltip} from "@mantine/core";
|
||||
import {IconTrash, IconUsersGroup} from "@tabler/icons-react";
|
||||
import {modals} from "@mantine/modals";
|
||||
import {isNumber} from "lodash";
|
||||
import { CRUDTableProps } from "../../../../../../types/CRUDTable.tsx";
|
||||
import { DealServiceSchema, GetServiceKitSchema, UserSchema } from "../../../../../../client";
|
||||
import { FC, useState } from "react";
|
||||
import { ActionIcon, Button, Flex, Modal, NumberInput, rem, Text, Title, Tooltip } from "@mantine/core";
|
||||
import { IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { isNumber } from "lodash";
|
||||
import SimpleUsersTable from "../../../../components/SimpleUsersTable/SimpleUsersTable.tsx";
|
||||
import {ServiceType} from "../../../../../../shared/enums/ServiceType.ts";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "../../../../../../redux/store.ts";
|
||||
import { ServiceType } from "../../../../../../shared/enums/ServiceType.ts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../../../../redux/store.ts";
|
||||
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||
|
||||
type RestProps = {
|
||||
onKitAdd?: (kit: GetServiceKitSchema) => void
|
||||
};
|
||||
type Props = CRUDTableProps<DealServiceSchema> & RestProps;
|
||||
const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKitAdd}) => {
|
||||
const DealServicesTable: FC<Props> = ({ items, onDelete, onCreate, onChange, onKitAdd }) => {
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
const {dealState} = useDealProductAndServiceTabState();
|
||||
const { dealState } = useDealProductAndServiceTabState();
|
||||
const isLocked = Boolean(dealState.deal?.billRequest);
|
||||
|
||||
const [currentService, setCurrentService] = useState<DealServiceSchema | undefined>();
|
||||
@@ -27,68 +27,70 @@ const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKi
|
||||
const onDeleteClick = (item: DealServiceSchema) => {
|
||||
if (!onDelete) return;
|
||||
onDelete(item);
|
||||
}
|
||||
};
|
||||
const onCreateClick = () => {
|
||||
if (!onCreate) return;
|
||||
console.log("228")
|
||||
const serviceIds = items.map(service => service.service.id);
|
||||
modals.openContextModal({
|
||||
modal: "addDealService",
|
||||
innerProps: {
|
||||
onCreate: onCreate,
|
||||
serviceIds
|
||||
serviceIds,
|
||||
category: dealState.deal?.category || undefined,
|
||||
},
|
||||
withCloseButton: false
|
||||
})
|
||||
}
|
||||
withCloseButton: false,
|
||||
});
|
||||
};
|
||||
const onQuantityChange = (item: DealServiceSchema, quantity: number) => {
|
||||
if (!onChange) return;
|
||||
onChange({
|
||||
...item,
|
||||
quantity
|
||||
})
|
||||
}
|
||||
quantity,
|
||||
});
|
||||
};
|
||||
const onPriceChange = (item: DealServiceSchema, price: number) => {
|
||||
if (!onChange) return;
|
||||
onChange({
|
||||
...item,
|
||||
price
|
||||
})
|
||||
}
|
||||
price,
|
||||
});
|
||||
};
|
||||
|
||||
const onEmployeeClick = (item: DealServiceSchema) => {
|
||||
if (!onChange) return;
|
||||
setCurrentService(item);
|
||||
setEmployeesModalVisible(true);
|
||||
}
|
||||
};
|
||||
const onEmployeeModalClose = () => {
|
||||
setEmployeesModalVisible(false);
|
||||
setCurrentService(undefined);
|
||||
}
|
||||
};
|
||||
const getCurrentEmployees = (): UserSchema[] => {
|
||||
if (!currentService) return [];
|
||||
const item = items.find(i => i.service.id === currentService.service.id)
|
||||
const item = items.find(i => i.service.id === currentService.service.id);
|
||||
if (!item) return [];
|
||||
return item.employees;
|
||||
}
|
||||
};
|
||||
const onEmployeesChange = (items: UserSchema[]) => {
|
||||
if (!currentService || !onChange) return;
|
||||
onChange({
|
||||
...currentService,
|
||||
employees: items
|
||||
employees: items,
|
||||
});
|
||||
}
|
||||
};
|
||||
const onAddKitClick = () => {
|
||||
if (!onKitAdd) return;
|
||||
modals.openContextModal({
|
||||
modal: "servicesKitSelectModal",
|
||||
innerProps: {
|
||||
onSelect: onKitAdd,
|
||||
serviceType: ServiceType.DEAL_SERVICE
|
||||
serviceType: ServiceType.DEAL_SERVICE,
|
||||
},
|
||||
withCloseButton: false
|
||||
withCloseButton: false,
|
||||
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
@@ -103,7 +105,7 @@ const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKi
|
||||
<Title
|
||||
order={3}
|
||||
w={"100%"}
|
||||
style={{textAlign: "center"}}
|
||||
style={{ textAlign: "center" }}
|
||||
mb={rem(10)}
|
||||
>Общие услуги</Title>
|
||||
|
||||
@@ -125,13 +127,13 @@ const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKi
|
||||
<ActionIcon
|
||||
disabled={isLocked}
|
||||
variant={"default"}>
|
||||
<IconTrash/>
|
||||
<IconTrash />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
{!authState.isGuest &&
|
||||
<Tooltip label="Сотрудники">
|
||||
<ActionIcon onClick={() => onEmployeeClick(service)} variant={"default"}>
|
||||
<IconUsersGroup/>
|
||||
<IconUsersGroup />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
}
|
||||
@@ -157,7 +159,7 @@ const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKi
|
||||
</Flex>
|
||||
|
||||
<Title
|
||||
style={{textAlign: "end"}}
|
||||
style={{ textAlign: "end" }}
|
||||
mt={rem(10)}
|
||||
order={3}
|
||||
>Итог: {items.reduce((acc, item) => acc + (item.price * item.quantity), 0)}₽</Title>
|
||||
@@ -196,6 +198,6 @@ const DealServicesTable: FC<Props> = ({items, onDelete, onCreate, onChange, onKi
|
||||
</Modal>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export default DealServicesTable;
|
||||
@@ -1,15 +1,15 @@
|
||||
import {CRUDTableProps} from "../../../../../../types/CRUDTable.tsx";
|
||||
import {DealProductServiceSchema, UserSchema} from "../../../../../../client";
|
||||
import {FC, useState} from "react";
|
||||
import { CRUDTableProps } from "../../../../../../types/CRUDTable.tsx";
|
||||
import { DealProductServiceSchema, UserSchema } from "../../../../../../client";
|
||||
import { FC, useState } from "react";
|
||||
import useProductServicesTableColumns from "./columns.tsx";
|
||||
import {BaseTable} from "../../../../../../components/BaseTable/BaseTable.tsx";
|
||||
import {MRT_TableOptions} from "mantine-react-table";
|
||||
import {ActionIcon, Button, Flex, Modal, rem, Tooltip} from "@mantine/core";
|
||||
import {IconEdit, IconTrash, IconUsersGroup} from "@tabler/icons-react";
|
||||
import {modals} from "@mantine/modals";
|
||||
import { BaseTable } from "../../../../../../components/BaseTable/BaseTable.tsx";
|
||||
import { MRT_TableOptions } from "mantine-react-table";
|
||||
import { ActionIcon, Button, Flex, Modal, rem, Tooltip } from "@mantine/core";
|
||||
import { IconEdit, IconTrash, IconUsersGroup } from "@tabler/icons-react";
|
||||
import { modals } from "@mantine/modals";
|
||||
import SimpleUsersTable from "../../../../components/SimpleUsersTable/SimpleUsersTable.tsx";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState} from "../../../../../../redux/store.ts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../../../../../redux/store.ts";
|
||||
import useDealProductAndServiceTabState from "../../hooks/useProductAndServiceTabState.tsx";
|
||||
|
||||
type RestProps = {
|
||||
@@ -26,13 +26,13 @@ const ProductServicesTable: FC<Props> = ({
|
||||
onDelete,
|
||||
onChange,
|
||||
onCopyServices,
|
||||
onKitAdd
|
||||
onKitAdd,
|
||||
}) => {
|
||||
const {dealState} = useDealProductAndServiceTabState();
|
||||
const { dealState } = useDealProductAndServiceTabState();
|
||||
const isLocked = Boolean(dealState.deal?.billRequest);
|
||||
const authState = useSelector((state: RootState) => state.auth);
|
||||
|
||||
const columns = useProductServicesTableColumns({data: items, quantity});
|
||||
const columns = useProductServicesTableColumns({ data: items, quantity });
|
||||
const serviceIds = items.map(service => service.service.id);
|
||||
|
||||
const [currentService, setCurrentService] = useState<DealProductServiceSchema | undefined>();
|
||||
@@ -45,11 +45,12 @@ const ProductServicesTable: FC<Props> = ({
|
||||
innerProps: {
|
||||
onCreate: onCreate,
|
||||
serviceIds,
|
||||
quantity
|
||||
quantity,
|
||||
category: dealState.deal?.category || undefined,
|
||||
},
|
||||
withCloseButton: false
|
||||
})
|
||||
}
|
||||
withCloseButton: false,
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeClick = (item: DealProductServiceSchema) => {
|
||||
if (!onChange) return;
|
||||
@@ -59,33 +60,35 @@ const ProductServicesTable: FC<Props> = ({
|
||||
element: item,
|
||||
onChange,
|
||||
serviceIds,
|
||||
quantity
|
||||
quantity,
|
||||
category: dealState.deal?.category || undefined,
|
||||
|
||||
},
|
||||
withCloseButton: false
|
||||
})
|
||||
}
|
||||
withCloseButton: false,
|
||||
});
|
||||
};
|
||||
const onEmployeeClick = (item: DealProductServiceSchema) => {
|
||||
if (!onChange) return;
|
||||
setCurrentService(item);
|
||||
setEmployeesModalVisible(true);
|
||||
}
|
||||
};
|
||||
const onEmployeeModalClose = () => {
|
||||
setEmployeesModalVisible(false);
|
||||
setCurrentService(undefined);
|
||||
}
|
||||
};
|
||||
const getCurrentEmployees = (): UserSchema[] => {
|
||||
if (!currentService) return [];
|
||||
const item = items.find(i => i.service.id === currentService.service.id)
|
||||
const item = items.find(i => i.service.id === currentService.service.id);
|
||||
if (!item) return [];
|
||||
return item.employees;
|
||||
}
|
||||
};
|
||||
const onEmployeesChange = (items: UserSchema[]) => {
|
||||
if (!currentService || !onChange) return;
|
||||
onChange({
|
||||
...currentService,
|
||||
employees: items
|
||||
employees: items,
|
||||
});
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
@@ -127,7 +130,7 @@ const ProductServicesTable: FC<Props> = ({
|
||||
|
||||
</Flex>
|
||||
),
|
||||
renderRowActions: ({row}) => (
|
||||
renderRowActions: ({ row }) => (
|
||||
<Flex gap="md">
|
||||
<Tooltip label="Удалить">
|
||||
<ActionIcon
|
||||
@@ -135,7 +138,7 @@ const ProductServicesTable: FC<Props> = ({
|
||||
onClick={() => {
|
||||
if (onDelete) onDelete(row.original);
|
||||
}} variant={"default"}>
|
||||
<IconTrash/>
|
||||
<IconTrash />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
@@ -145,13 +148,13 @@ const ProductServicesTable: FC<Props> = ({
|
||||
|
||||
onClick={() => onChangeClick(row.original)}
|
||||
variant={"default"}>
|
||||
<IconEdit/>
|
||||
<IconEdit />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
{!authState.isGuest &&
|
||||
<Tooltip label="Сотрудники">
|
||||
<ActionIcon onClick={() => onEmployeeClick(row.original)} variant={"default"}>
|
||||
<IconUsersGroup/>
|
||||
<IconUsersGroup />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
}
|
||||
@@ -177,6 +180,6 @@ const ProductServicesTable: FC<Props> = ({
|
||||
</Modal>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export default ProductServicesTable;
|
||||
@@ -1,24 +1,24 @@
|
||||
import {FC, useEffect, useState} from "react";
|
||||
import styles from './LeadsPage.module.css';
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import styles from "./LeadsPage.module.css";
|
||||
import Board from "../../../components/Dnd/Board/Board.tsx";
|
||||
import {DragDropContext, Droppable, DropResult} from "@hello-pangea/dnd";
|
||||
import {useDealSummaries} from "../hooks/useDealSummaries.tsx";
|
||||
import {DealStatus, getDealStatusByName} from "../../../shared/enums/DealStatus.ts";
|
||||
import { DragDropContext, Droppable, DropResult } from "@hello-pangea/dnd";
|
||||
import { useDealSummaries } from "../hooks/useDealSummaries.tsx";
|
||||
import { DealStatus, getDealStatusByName } from "../../../shared/enums/DealStatus.ts";
|
||||
import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
|
||||
import DealEditDrawer from "../drawers/DealEditDrawer/DealEditDrawer.tsx";
|
||||
import {DealPageContextProvider} from "../contexts/DealPageContext.tsx";
|
||||
import {modals} from "@mantine/modals";
|
||||
import {DealService, DealSummaryReorderRequest} from "../../../client";
|
||||
import {ActionIcon, Flex, rem, Text} from "@mantine/core";
|
||||
import { DealPageContextProvider } from "../contexts/DealPageContext.tsx";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { DealService, DealSummaryReorderRequest } from "../../../client";
|
||||
import { ActionIcon, Flex, rem, Text } from "@mantine/core";
|
||||
import classNames from "classnames";
|
||||
import {notifications} from "../../../shared/lib/notifications.ts";
|
||||
import {IconMenu2, IconMenuDeep} from "@tabler/icons-react";
|
||||
import { notifications } from "../../../shared/lib/notifications.ts";
|
||||
import { IconMenu2, IconMenuDeep } from "@tabler/icons-react";
|
||||
import useDealsPageState from "../../DealsPage/hooks/useDealsPageState.tsx";
|
||||
import DealStatusSelect from "../../DealsPage/components/DealStatusSelect/DealStatusSelect.tsx";
|
||||
import BaseMarketplaceSelect from "../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
|
||||
import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx";
|
||||
import DealsTable from "../../DealsPage/components/DealsTable/DealsTable.tsx";
|
||||
import {motion} from "framer-motion";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
enum DisplayMode {
|
||||
BOARD,
|
||||
@@ -26,9 +26,9 @@ enum DisplayMode {
|
||||
}
|
||||
|
||||
export const LeadsPage: FC = () => {
|
||||
const {data, form} = useDealsPageState();
|
||||
const { data, form } = useDealsPageState();
|
||||
|
||||
const {summariesRaw, refetch} = useDealSummaries();
|
||||
const { summariesRaw, refetch } = useDealSummaries();
|
||||
const [summaries, setSummaries] = useState(summariesRaw);
|
||||
const [displayMode, setDisplayMode] = useState<DisplayMode>(DisplayMode.BOARD);
|
||||
const [isDragEnded, setIsDragEnded] = useState(true);
|
||||
@@ -46,19 +46,19 @@ export const LeadsPage: FC = () => {
|
||||
Вы действительно хотите удалить сделку {summary.name}?
|
||||
</Flex>,
|
||||
onConfirm: () => {
|
||||
DealService.deleteDeal({requestBody: {dealId: dealId}})
|
||||
.then(async ({ok, message}) => {
|
||||
notifications.guess(ok, {message});
|
||||
DealService.deleteDeal({ requestBody: { dealId: dealId } })
|
||||
.then(async ({ ok, message }) => {
|
||||
notifications.guess(ok, { message });
|
||||
if (!ok) return;
|
||||
await refetch();
|
||||
})
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
confirm: "Удалить",
|
||||
cancel: "Отмена"
|
||||
}
|
||||
cancel: "Отмена",
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
const onSuccess = (dealId: number) => {
|
||||
const summary = summaries.find(summary => summary.id == dealId);
|
||||
if (!summary) return;
|
||||
@@ -69,19 +69,19 @@ export const LeadsPage: FC = () => {
|
||||
Вы действительно хотите завершить сделку {summary.name}?
|
||||
</Flex>,
|
||||
onConfirm: () => {
|
||||
DealService.completeDeal({requestBody: {dealId: dealId}})
|
||||
.then(async ({ok, message}) => {
|
||||
notifications.guess(ok, {message});
|
||||
DealService.completeDeal({ requestBody: { dealId: dealId } })
|
||||
.then(async ({ ok, message }) => {
|
||||
notifications.guess(ok, { message });
|
||||
if (!ok) return;
|
||||
await refetch();
|
||||
})
|
||||
});
|
||||
},
|
||||
labels: {
|
||||
confirm: "Завершить",
|
||||
cancel: "Отмена"
|
||||
}
|
||||
cancel: "Отмена",
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
const onDragEnd = async (result: DropResult) => {
|
||||
setIsDragEnded(true);
|
||||
// If there is no changes
|
||||
@@ -97,11 +97,11 @@ export const LeadsPage: FC = () => {
|
||||
|
||||
// Checking if it is custom actions
|
||||
const droppableId = result.destination.droppableId;
|
||||
if (droppableId === 'DELETE') {
|
||||
if (droppableId === "DELETE") {
|
||||
onDelete(dealId);
|
||||
return;
|
||||
}
|
||||
if (droppableId === 'SUCCESS') {
|
||||
if (droppableId === "SUCCESS") {
|
||||
onSuccess(dealId);
|
||||
return;
|
||||
}
|
||||
@@ -109,10 +109,10 @@ export const LeadsPage: FC = () => {
|
||||
const request: Partial<DealSummaryReorderRequest> = {
|
||||
dealId: dealId,
|
||||
index: result.destination.index,
|
||||
status: status
|
||||
}
|
||||
status: status,
|
||||
};
|
||||
if (status == summary.status) {
|
||||
DealService.reorderDealSummaries({requestBody: request as DealSummaryReorderRequest})
|
||||
DealService.reorderDealSummaries({ requestBody: request as DealSummaryReorderRequest })
|
||||
.then(async response => {
|
||||
setSummaries(response.summaries);
|
||||
await refetch();
|
||||
@@ -120,33 +120,33 @@ export const LeadsPage: FC = () => {
|
||||
return;
|
||||
}
|
||||
modals.openContextModal({
|
||||
modal: 'enterDeadline',
|
||||
modal: "enterDeadline",
|
||||
title: "Необходимо указать дедлайн",
|
||||
innerProps: {
|
||||
onSubmit: (event) => DealService.reorderDealSummaries({requestBody: event})
|
||||
onSubmit: (event) => DealService.reorderDealSummaries({ requestBody: event })
|
||||
.then(async response => {
|
||||
setSummaries(response.summaries);
|
||||
await refetch();
|
||||
}),
|
||||
request: request
|
||||
}
|
||||
request: request,
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
const getTableBody = () => {
|
||||
return (
|
||||
<motion.div
|
||||
key={displayMode}
|
||||
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
|
||||
<DealsTable items={data}/>
|
||||
<DealsTable items={data} />
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
const getBoardBody = () => {
|
||||
return (
|
||||
|
||||
@@ -154,12 +154,12 @@ export const LeadsPage: FC = () => {
|
||||
style={{
|
||||
display: "flex",
|
||||
height: "100%",
|
||||
flex: 1
|
||||
flex: 1,
|
||||
}}
|
||||
key={displayMode}
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
|
||||
<DragDropContext
|
||||
@@ -170,24 +170,24 @@ export const LeadsPage: FC = () => {
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
style={{flex: 1}}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
|
||||
<div className={styles['boards']}>
|
||||
<div className={styles["boards"]}>
|
||||
<Board
|
||||
withCreateButton
|
||||
summaries={summaries
|
||||
.filter(summary => summary.status == DealStatus.AWAITING_ACCEPTANCE)}
|
||||
title={"Ожидает приемки"}
|
||||
droppableId={"AWAITING_ACCEPTANCE"}
|
||||
color={'#4A90E2'}
|
||||
color={"#4A90E2"}
|
||||
/>
|
||||
<Board
|
||||
summaries={summaries
|
||||
.filter(summary => summary.status == DealStatus.PACKAGING)}
|
||||
title={"Упаковка"}
|
||||
droppableId={"PACKAGING"}
|
||||
color={'#F5A623'}
|
||||
color={"#F5A623"}
|
||||
|
||||
/>
|
||||
<Board
|
||||
@@ -195,7 +195,7 @@ export const LeadsPage: FC = () => {
|
||||
.filter(summary => summary.status == DealStatus.AWAITING_SHIPMENT)}
|
||||
title={"Ожидает отгрузки"}
|
||||
droppableId={"AWAITING_SHIPMENT"}
|
||||
color={'#7ED321'}
|
||||
color={"#7ED321"}
|
||||
|
||||
/>
|
||||
<Board
|
||||
@@ -203,7 +203,7 @@ export const LeadsPage: FC = () => {
|
||||
.filter(summary => summary.status == DealStatus.AWAITING_PAYMENT)}
|
||||
title={"Ожидает оплаты"}
|
||||
droppableId={"AWAITING_PAYMENT"}
|
||||
color={'#D0021B'}
|
||||
color={"#D0021B"}
|
||||
|
||||
/>
|
||||
<Board
|
||||
@@ -211,15 +211,15 @@ export const LeadsPage: FC = () => {
|
||||
.filter(summary => summary.status == DealStatus.COMPLETED)}
|
||||
title={"Завершена"}
|
||||
droppableId={"COMPLETED"}
|
||||
color={'#417505'}
|
||||
color={"#417505"}
|
||||
/>
|
||||
</div>
|
||||
<Flex justify={"space-between"} gap={rem(10)}>
|
||||
<div
|
||||
className={
|
||||
classNames(
|
||||
styles['delete'],
|
||||
isDragEnded && styles['delete-hidden']
|
||||
styles["delete"],
|
||||
isDragEnded && styles["delete-hidden"],
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -250,8 +250,8 @@ export const LeadsPage: FC = () => {
|
||||
<div
|
||||
className={
|
||||
classNames(
|
||||
styles['delete'],
|
||||
isDragEnded && styles['delete-hidden']
|
||||
styles["delete"],
|
||||
isDragEnded && styles["delete-hidden"],
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -284,11 +284,11 @@ export const LeadsPage: FC = () => {
|
||||
</DragDropContext>
|
||||
</motion.div>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
const getBody = () => {
|
||||
return displayMode === DisplayMode.TABLE ? getTableBody() : getBoardBody();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<PageBlock
|
||||
fullHeight
|
||||
@@ -302,7 +302,7 @@ export const LeadsPage: FC = () => {
|
||||
>
|
||||
<DealPageContextProvider>
|
||||
<PageBlock
|
||||
style={{flex: 0}}
|
||||
style={{ flex: 0 }}
|
||||
>
|
||||
<Flex
|
||||
align={"center"}
|
||||
@@ -326,7 +326,7 @@ export const LeadsPage: FC = () => {
|
||||
|
||||
}>
|
||||
<IconMenuDeep
|
||||
style={{rotate: "-90deg"}}
|
||||
style={{ rotate: "-90deg" }}
|
||||
/>
|
||||
</ActionIcon>
|
||||
<ActionIcon
|
||||
@@ -346,14 +346,14 @@ export const LeadsPage: FC = () => {
|
||||
</Flex>
|
||||
<motion.div
|
||||
key={displayMode}
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: 1}}
|
||||
transition={{duration: 0.2}}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<div
|
||||
|
||||
className={styles['top-panel']}
|
||||
style={{display: displayMode === DisplayMode.TABLE ? "flex" : "none"}}
|
||||
className={styles["top-panel"]}
|
||||
style={{ display: displayMode === DisplayMode.TABLE ? "flex" : "none" }}
|
||||
>
|
||||
<DealStatusSelect
|
||||
onClear={() => form.setFieldValue("dealStatus", null)}
|
||||
@@ -384,7 +384,7 @@ export const LeadsPage: FC = () => {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flex: 1,
|
||||
height: "100%"
|
||||
height: "100%",
|
||||
}}>
|
||||
{getBody()}
|
||||
</PageBlock>
|
||||
@@ -394,5 +394,5 @@ export const LeadsPage: FC = () => {
|
||||
|
||||
</PageBlock>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user