Files
Fulfillment-Frontend/src/pages/LeadsPage/drawers/DealEditDrawer/tabs/DealEditDrawerGeneralTab.tsx
2024-09-22 22:09:11 +03:00

273 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { FC } from "react";
import { useDealPageContext } from "../../../contexts/DealPageContext.tsx";
import {
ActionIcon,
Button,
Checkbox,
Divider,
Fieldset,
Flex,
Group,
rem,
Textarea,
TextInput,
Tooltip,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { ClientService, DealSchema, DealService, ShippingWarehouseSchema } 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";
import ShippingWarehouseAutocomplete
from "../../../../../components/Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
import { ButtonCopyControlled } from "../../../../../components/ButtonCopyControlled/ButtonCopyControlled.tsx";
import { useClipboard } from "@mantine/hooks";
import ButtonCopy from "../../../../../components/ButtonCopy/ButtonCopy.tsx";
import FileSaver from "file-saver";
import { getCurrentDateTimeForFilename } from "../../../../../shared/lib/date.ts";
import { IconPrinter } from "@tabler/icons-react";
type Props = {
deal: DealSchema
}
type FormType = Omit<DealSchema, "statusHistory" | "services" | "products">
const Content: FC<Props> = ({ deal }) => {
const { setSelectedDeal } = useDealPageContext();
const clipboard = useClipboard();
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, shippingWarehouse: values.shippingWarehouse?.toString() },
},
}).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);
};
const isShippingWarehouse = (value: (ShippingWarehouseSchema | string | null | undefined)): value is ShippingWarehouseSchema => {
return !["string", "null", "undefined"].includes((typeof value));
};
const onCopyGuestUrlClick = () => {
DealService.createDealGuestUrl({
requestBody: {
dealId: deal.id,
},
}).then(({ ok, message, url }) => {
if (!ok)
notifications.guess(ok, { message });
clipboard.copy(
`${window.location.origin}/${url}`,
);
});
};
return (
<form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
<Flex direction={"column"}>
<Fieldset legend={`Общие параметры [ID: ${deal.id}]`}>
<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]} />
<Textarea
label={"Коментарий к сделке"}
placeholder={"Введите коментарий к сделке"}
{...form.getInputProps("comment")}
/>
<ShippingWarehouseAutocomplete
placeholder={"Введите склад отгрузки"}
label={"Склад отгрузки"}
value={isShippingWarehouse(form.values.shippingWarehouse) ? form.values.shippingWarehouse : undefined}
onChange={event => {
if (isShippingWarehouse(event)) {
form.getInputProps("shippingWarehouse").onChange(event.name);
return;
}
form.getInputProps("shippingWarehouse").onChange(event);
}}
/>
</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"}>
<Flex gap={rem(10)} align={"center"} justify={"space-between"}>
<Tooltip
label={"Распечатать сделку"}
>
<ActionIcon
onClick={() => {
const pdfWindow = window.open(`${import.meta.env.VITE_API_URL}/deal/detailedDocument/${deal.id}`);
if (!pdfWindow) return;
pdfWindow.print();
}}
variant={"default"}>
<IconPrinter />
</ActionIcon>
</Tooltip>
<Flex gap={rem(10)}>
{(deal.billRequest && deal.billRequest.pdfUrl) ?
<ButtonCopy
onCopiedLabel={"Ссылка скопирована в буфер обмена"}
value={deal.billRequest.pdfUrl}
>
Ссылка на оплату
</ButtonCopy>
:
<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`);
}}
copied={false}
onCopiedLabel={"Ссылка скопирована в буфер обмена"}
>
Ссылка на оплату (PDF)
</ButtonCopyControlled>
}
<ButtonCopyControlled
onCopyClick={onCopyGuestUrlClick}
onCopiedLabel={"Ссылка скопирована в буфер обмена"}
copied={clipboard.copied}>
Ссылка на редактирование
</ButtonCopyControlled>
</Flex>
</Flex>
<Flex gap={rem(10)}>
<Checkbox
label={"Оплачен"}
checked={deal.billRequest?.paid || false}
disabled
/>
<Checkbox
label={"Сделка завершена"}
{...form.getInputProps("isCompleted")}
/>
<Checkbox
label={"Сделка удалена"}
{...form.getInputProps("isDeleted")}
/>
</Flex>
</Flex>
<Divider
orientation={"vertical"}
/>
<Group align={"center"} justify={"center"}>
<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>
</Flex>
</Flex>
</form>
);
};
const DealEditDrawerGeneralTab: FC = () => {
const { selectedDeal } = useDealPageContext();
if (!selectedDeal) return <>No deal selected</>;
return (
<Content deal={selectedDeal} />
);
};
export default DealEditDrawerGeneralTab;