new crm
parent
19adacfcf6
commit
4628d56ac5
|
@ -24,6 +24,7 @@ const ViewEquipmentDocumentations = lazy(() =>
|
||||||
const Consoles = lazy(() => import("../../Pages/Consoles"));
|
const Consoles = lazy(() => import("../../Pages/Consoles"));
|
||||||
const RoboticsRobots = lazy(() => import("../../Pages/Robotics/Robots"));
|
const RoboticsRobots = lazy(() => import("../../Pages/Robotics/Robots"));
|
||||||
const Crm = lazy(() => import("../../Pages/Crm"));
|
const Crm = lazy(() => import("../../Pages/Crm"));
|
||||||
|
const CrmTest = lazy(() => import("../../Pages/CrmTest/CrmTest"));
|
||||||
|
|
||||||
export default function AppRoutes({ userSession, setUserSession }) {
|
export default function AppRoutes({ userSession, setUserSession }) {
|
||||||
const appContext = useAppContext();
|
const appContext = useAppContext();
|
||||||
|
@ -248,10 +249,10 @@ export default function AppRoutes({ userSession, setUserSession }) {
|
||||||
Constants.PERMISSIONS.CRM.SETTER_CLOSER.VIEW
|
Constants.PERMISSIONS.CRM.SETTER_CLOSER.VIEW
|
||||||
) && (
|
) && (
|
||||||
<Route
|
<Route
|
||||||
path={`${Constants.ROUTE_PATHS.CRM}:paramType/:paramDealPhase`}
|
path={Constants.ROUTE_PATHS.CRM_TEST}
|
||||||
element={
|
element={
|
||||||
<MySupsenseFallback>
|
<MySupsenseFallback>
|
||||||
<Crm />
|
<CrmTest />
|
||||||
</MySupsenseFallback>
|
</MySupsenseFallback>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -268,3 +269,24 @@ export default function AppRoutes({ userSession, setUserSession }) {
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{hasOnePermission(
|
||||||
|
appContext.userPermissions,
|
||||||
|
Constants.PERMISSIONS.CRM.CUSTOMERS.VIEW,
|
||||||
|
Constants.PERMISSIONS.CRM.DMC_PIPELINE.VIEW,
|
||||||
|
Constants.PERMISSIONS.CRM.SETTER_CLOSER.VIEW
|
||||||
|
) && (
|
||||||
|
<Route
|
||||||
|
path={`${Constants.ROUTE_PATHS.CRM}:paramType/:paramDealPhase`}
|
||||||
|
element={
|
||||||
|
<MySupsenseFallback>
|
||||||
|
<Crm />
|
||||||
|
</MySupsenseFallback>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
*/
|
||||||
|
|
|
@ -169,6 +169,19 @@ export function SideMenuContent({
|
||||||
children: [],
|
children: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
hasPermission(
|
||||||
|
appContext.userPermissions,
|
||||||
|
Constants.PERMISSIONS.CRM.CUSTOMERS.VIEW
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
crmGroup.children.push({
|
||||||
|
label: t("sideMenu.crm.customers"),
|
||||||
|
icon: <FileTextOutlined />,
|
||||||
|
key: Constants.ROUTE_PATHS.CRM_TEST,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/*
|
||||||
if (
|
if (
|
||||||
hasPermission(
|
hasPermission(
|
||||||
appContext.userPermissions,
|
appContext.userPermissions,
|
||||||
|
@ -207,7 +220,7 @@ export function SideMenuContent({
|
||||||
key: `${Constants.ROUTE_PATHS.CRM}${Constants.CRM_TYPE.SETTER_CLOSER}/1`,
|
key: `${Constants.ROUTE_PATHS.CRM}${Constants.CRM_TYPE.SETTER_CLOSER}/1`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
items.push(crmGroup);
|
items.push(crmGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1061,6 +1061,8 @@ export function handleWebSocketMessage(
|
||||||
crmContext.setCustomers((arr) => {
|
crmContext.setCustomers((arr) => {
|
||||||
const newArr = [...arr];
|
const newArr = [...arr];
|
||||||
|
|
||||||
|
console.log("before", arr);
|
||||||
|
|
||||||
const arrIndex = arr.findIndex((customer) => customer.Id === body.Id);
|
const arrIndex = arr.findIndex((customer) => customer.Id === body.Id);
|
||||||
|
|
||||||
if (arrIndex !== -1) {
|
if (arrIndex !== -1) {
|
||||||
|
@ -1068,10 +1070,14 @@ export function handleWebSocketMessage(
|
||||||
for (const property in body) {
|
for (const property in body) {
|
||||||
if (body[property] !== undefined && property !== "Id") {
|
if (body[property] !== undefined && property !== "Id") {
|
||||||
newArr[arrIndex][property] = body[property];
|
newArr[arrIndex][property] = body[property];
|
||||||
|
|
||||||
|
console.log("updated", property, body, body[property]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("after", newArr);
|
||||||
|
|
||||||
return newArr;
|
return newArr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,24 @@ function CustomerDrawer({ isOpen, setIsOpen, onClose, notificationApi }) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRequestError = (status) => {
|
||||||
|
if (status === 409) {
|
||||||
|
notificationApi["error"]({
|
||||||
|
message: t("crm.tabContent.request.duplicateCompanyError.message"),
|
||||||
|
description: t(
|
||||||
|
"crm.tabContent.request.duplicateCompanyError.description"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notificationApi["error"]({
|
||||||
|
message: "test",
|
||||||
|
description: "here",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (crmContext.openDrawerCustomerId.current === null) return;
|
if (crmContext.openDrawerCustomerId.current === null) return;
|
||||||
|
|
||||||
|
@ -315,25 +333,7 @@ function CustomerDrawer({ isOpen, setIsOpen, onClose, notificationApi }) {
|
||||||
crmContext.openDrawerCustomerId.current = false;
|
crmContext.openDrawerCustomerId.current = false;
|
||||||
handleCloseDrawer();
|
handleCloseDrawer();
|
||||||
})
|
})
|
||||||
.catch((status) => {
|
.catch((status) => handleRequestError(status));
|
||||||
if (status === 409) {
|
|
||||||
notificationApi["error"]({
|
|
||||||
message: t(
|
|
||||||
"crm.tabContent.request.duplicateCompanyError.message"
|
|
||||||
),
|
|
||||||
description: t(
|
|
||||||
"crm.tabContent.request.duplicateCompanyError.description"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notificationApi["error"]({
|
|
||||||
message: "test",
|
|
||||||
description: "here",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsOpen(true);
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,31 +362,9 @@ function CustomerDrawer({ isOpen, setIsOpen, onClose, notificationApi }) {
|
||||||
"POST",
|
"POST",
|
||||||
updatedCustomer
|
updatedCustomer
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => handleCloseDrawer())
|
||||||
handleCloseDrawer();
|
.catch((status) => handleRequestError(status));
|
||||||
})
|
|
||||||
.catch((status) => {
|
|
||||||
if (status === 409) {
|
|
||||||
notificationApi["error"]({
|
|
||||||
message: t(
|
|
||||||
"crm.tabContent.request.duplicateCompanyError.message"
|
|
||||||
),
|
|
||||||
description: t(
|
|
||||||
"crm.tabContent.request.duplicateCompanyError.description"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notificationApi["error"]({
|
|
||||||
message: "test",
|
|
||||||
description: "here",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsOpen(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//handleCloseDrawer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCustomerRequest = () => customerRequest();
|
const handleCustomerRequest = () => customerRequest();
|
||||||
|
|
|
@ -0,0 +1,816 @@
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Col,
|
||||||
|
Collapse,
|
||||||
|
Drawer,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Row,
|
||||||
|
Segmented,
|
||||||
|
Select,
|
||||||
|
Space,
|
||||||
|
Table,
|
||||||
|
Tabs,
|
||||||
|
Typography,
|
||||||
|
notification,
|
||||||
|
} from "antd";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import {
|
||||||
|
AppStyle,
|
||||||
|
FormatDatetime,
|
||||||
|
myFetch,
|
||||||
|
showUnkownErrorNotification,
|
||||||
|
wsConnectionCustomEventName,
|
||||||
|
} from "../../utils";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { useCrmContext } from "../../Contexts/CrmContext";
|
||||||
|
import "@mdxeditor/editor/style.css";
|
||||||
|
import { MDXEditor } from "@mdxeditor/editor/MDXEditor";
|
||||||
|
import { headingsPlugin } from "@mdxeditor/editor/plugins/headings";
|
||||||
|
import { listsPlugin } from "@mdxeditor/editor/plugins/lists";
|
||||||
|
import { quotePlugin } from "@mdxeditor/editor/plugins/quote";
|
||||||
|
import { thematicBreakPlugin } from "@mdxeditor/editor/plugins/thematic-break";
|
||||||
|
import { toolbarPlugin } from "@mdxeditor/editor/plugins/toolbar";
|
||||||
|
import { BoldItalicUnderlineToggles } from "@mdxeditor/editor/plugins/toolbar/components/BoldItalicUnderlineToggles";
|
||||||
|
import { UndoRedo } from "@mdxeditor/editor/plugins/toolbar/components/UndoRedo";
|
||||||
|
import { linkPlugin } from "@mdxeditor/editor/plugins/link";
|
||||||
|
import { markdownShortcutPlugin } from "@mdxeditor/editor/plugins/markdown-shortcut";
|
||||||
|
import { MySupsenseFallback } from "../../Components/MySupsenseFallback";
|
||||||
|
import { linkDialogPlugin } from "@mdxeditor/editor";
|
||||||
|
import { tablePlugin } from "@mdxeditor/editor";
|
||||||
|
import { frontmatterPlugin } from "@mdxeditor/editor";
|
||||||
|
|
||||||
|
const CRM_TYPE = {
|
||||||
|
CUSTOMERS: 0,
|
||||||
|
DMC_PIPELINE: 1,
|
||||||
|
SETTER_CLOSER: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CrmTest() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const crmContext = useCrmContext();
|
||||||
|
|
||||||
|
const [isRequesting, setIsRequesting] = useState(false);
|
||||||
|
|
||||||
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
notification.useNotification();
|
||||||
|
|
||||||
|
// used for the segmented component on top of the page
|
||||||
|
const [selectedSegmentedTypeValue, setSelectedSegmentedTypeValue] =
|
||||||
|
useState(0);
|
||||||
|
|
||||||
|
const title =
|
||||||
|
selectedSegmentedTypeValue === CRM_TYPE.CUSTOMERS
|
||||||
|
? "crm.customers.pageTitle"
|
||||||
|
: selectedSegmentedTypeValue === CRM_TYPE.DMC_PIPELINE
|
||||||
|
? "crm.dmcPipeline.pageTitle"
|
||||||
|
: "crm.setterCloser.pageTitle";
|
||||||
|
|
||||||
|
const segmentedOptions = t(
|
||||||
|
selectedSegmentedTypeValue === CRM_TYPE.DMC_PIPELINE
|
||||||
|
? "crm.dmcPipeline.segmentedOptions"
|
||||||
|
: "crm.setterCloser.segmentedOptions",
|
||||||
|
{
|
||||||
|
returnObjects: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [
|
||||||
|
selectedDmcPipelineSegmentedValue,
|
||||||
|
setSelectedDmcPipelineSegmentedValue,
|
||||||
|
] = useState(0);
|
||||||
|
const [
|
||||||
|
selectedSetterCloserSegmentedValue,
|
||||||
|
setSelectedSetterCloserSegmentedValue,
|
||||||
|
] = useState(0);
|
||||||
|
|
||||||
|
const getTableContent = () => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: t("crm.table.firstName"),
|
||||||
|
dataIndex: "firstName",
|
||||||
|
key: "firstName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.lastName"),
|
||||||
|
dataIndex: "lastName",
|
||||||
|
key: "lastName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.createdAt"),
|
||||||
|
dataIndex: "createdAt",
|
||||||
|
key: "createdAt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.telephone"),
|
||||||
|
dataIndex: "telephone",
|
||||||
|
key: "telephone",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.email"),
|
||||||
|
dataIndex: "email",
|
||||||
|
key: "email",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.lastContact"),
|
||||||
|
dataIndex: "lastContact",
|
||||||
|
key: "lastContact",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("crm.table.createdBy"),
|
||||||
|
dataIndex: "createdBy",
|
||||||
|
key: "createdBy",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTableItems = () => {
|
||||||
|
let data = crmContext.customers;
|
||||||
|
let items = [];
|
||||||
|
|
||||||
|
if (selectedSegmentedTypeValue === CRM_TYPE.DMC_PIPELINE) {
|
||||||
|
data = data.filter((item) => item.Pipeline === 1);
|
||||||
|
data = data.filter(
|
||||||
|
(item) => item.DealPhase === selectedDmcPipelineSegmentedValue + 1
|
||||||
|
);
|
||||||
|
} else if (selectedSegmentedTypeValue === CRM_TYPE.SETTER_CLOSER) {
|
||||||
|
data = data.filter((item) => item.Pipeline === 2);
|
||||||
|
data = data.filter(
|
||||||
|
(item) => item.DealPhase === selectedSetterCloserSegmentedValue + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
items.push({
|
||||||
|
key: item.Id,
|
||||||
|
id: item.Id,
|
||||||
|
firstName: item.FirstName,
|
||||||
|
lastName: item.LastName,
|
||||||
|
createdAt: FormatDatetime(item.CreatedAt),
|
||||||
|
telephone: item.Telephone,
|
||||||
|
email: item.Email,
|
||||||
|
lastContact: FormatDatetime(item.LastContact),
|
||||||
|
createdBy: item.CreatedBy,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const customersRequest = () => {
|
||||||
|
setIsRequesting(true);
|
||||||
|
|
||||||
|
myFetch(`/crm/customers`, "GET").then((data) => {
|
||||||
|
if (data === undefined || data === null) return;
|
||||||
|
|
||||||
|
crmContext.setCustomers(data);
|
||||||
|
setIsRequesting(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
customersRequest();
|
||||||
|
|
||||||
|
const handleCustomersRequest = () => customersRequest();
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
wsConnectionCustomEventName,
|
||||||
|
handleCustomersRequest
|
||||||
|
);
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
document.removeEventListener(
|
||||||
|
wsConnectionCustomEventName,
|
||||||
|
handleCustomersRequest
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{notificationContextHolder}
|
||||||
|
|
||||||
|
<Segmented
|
||||||
|
value={selectedSegmentedTypeValue}
|
||||||
|
onChange={(value) => {
|
||||||
|
setSelectedSegmentedTypeValue(value);
|
||||||
|
}}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
value: CRM_TYPE.CUSTOMERS,
|
||||||
|
label: "All customers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: CRM_TYPE.DMC_PIPELINE,
|
||||||
|
label: "DMC Pipeline",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: CRM_TYPE.SETTER_CLOSER,
|
||||||
|
label: "Setter Closer",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
block
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography.Title level={4}>{t(title)}</Typography.Title>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
crmContext.openDrawerCustomerId.current = "new";
|
||||||
|
crmContext.currentDrawerCustomerRef.current = null;
|
||||||
|
|
||||||
|
setIsDrawerOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("crm.buttonNew")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedSegmentedTypeValue !== CRM_TYPE.CUSTOMERS ? (
|
||||||
|
<Segmented
|
||||||
|
value={
|
||||||
|
selectedSegmentedTypeValue === CRM_TYPE.DMC_PIPELINE
|
||||||
|
? selectedDmcPipelineSegmentedValue
|
||||||
|
: selectedSetterCloserSegmentedValue
|
||||||
|
}
|
||||||
|
onChange={(value) => {
|
||||||
|
if (selectedSegmentedTypeValue === CRM_TYPE.DMC_PIPELINE) {
|
||||||
|
setSelectedDmcPipelineSegmentedValue(value);
|
||||||
|
} else {
|
||||||
|
setSelectedSetterCloserSegmentedValue(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
options={segmentedOptions.map((item, index) => {
|
||||||
|
return {
|
||||||
|
value: index,
|
||||||
|
label: item,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
style={{ marginBottom: AppStyle.app.margin }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ height: 44 }} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Table
|
||||||
|
scroll={{ x: "max-content" }}
|
||||||
|
columns={getTableContent()}
|
||||||
|
dataSource={getTableItems()}
|
||||||
|
loading={isRequesting}
|
||||||
|
pagination
|
||||||
|
onRow={(record) => {
|
||||||
|
return {
|
||||||
|
onClick: () => {
|
||||||
|
setIsDrawerOpen(true);
|
||||||
|
crmContext.openDrawerCustomerId.current = record.id;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomerDrawer
|
||||||
|
isOpen={isDrawerOpen}
|
||||||
|
setIsOpen={setIsDrawerOpen}
|
||||||
|
onClose={() => setIsDrawerOpen(false)}
|
||||||
|
notificationApi={notificationApi}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function CustomerDrawer({ isOpen, setIsOpen, onClose, notificationApi }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const crmContext = useCrmContext();
|
||||||
|
|
||||||
|
const [formDealInfo] = Form.useForm();
|
||||||
|
|
||||||
|
const tabItems = [
|
||||||
|
{
|
||||||
|
key: "0",
|
||||||
|
label: t("crm.tabs.dealInfo"),
|
||||||
|
children: <TabContentDealInfo form={formDealInfo} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "1",
|
||||||
|
label: t("crm.tabs.activities"),
|
||||||
|
children: <TabContentActivities />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "2",
|
||||||
|
label: t("crm.tabs.notes"),
|
||||||
|
children: (
|
||||||
|
<TabContentNotes
|
||||||
|
notes={
|
||||||
|
crmContext.currentDrawerCustomer === null ||
|
||||||
|
crmContext.currentDrawerCustomer.Notes === null
|
||||||
|
? ""
|
||||||
|
: crmContext.currentDrawerCustomer.Notes
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState(tabItems[0].key);
|
||||||
|
|
||||||
|
const customerRequest = () => {
|
||||||
|
if (!isOpen) return;
|
||||||
|
|
||||||
|
myFetch(
|
||||||
|
`/crm/customer/view/${crmContext.openDrawerCustomerId.current}`,
|
||||||
|
"GET"
|
||||||
|
).then((data) => {
|
||||||
|
crmContext.currentDrawerCustomerRef.current = data;
|
||||||
|
|
||||||
|
formDealInfo.setFieldsValue({
|
||||||
|
Pipeline: data.Pipeline,
|
||||||
|
DealPhase: data.DealPhase,
|
||||||
|
FirstName: data.FirstName,
|
||||||
|
LastName: data.LastName,
|
||||||
|
Telephone: data.Telephone,
|
||||||
|
Email: data.Email,
|
||||||
|
Company: data.Company,
|
||||||
|
ZipCode: data.ZipCode,
|
||||||
|
Address: data.Address,
|
||||||
|
City: data.City,
|
||||||
|
Country: data.Country,
|
||||||
|
FederalState: data.FederalState,
|
||||||
|
Website: data.Website,
|
||||||
|
LeadOrigin: data.LeadOrigin,
|
||||||
|
NumberOfEmployees: data.NumberOfEmployees,
|
||||||
|
NumberOfJobsSearchedFor: data.NumberOfJobsSearchedFor,
|
||||||
|
JobTitle: data.JobTitle,
|
||||||
|
NumberOfEmployeesRequired: data.NumberOfEmployeesRequired,
|
||||||
|
HowLongHadHeBeenSearching: data.HowLongHadHeBeenSearching,
|
||||||
|
Turnover: data.Turnover,
|
||||||
|
DateOfcompletion: data.DateOfcompletion,
|
||||||
|
OrderVolume: data.OrderVolume,
|
||||||
|
NumberOfInstallments: data.NumberOfInstallments,
|
||||||
|
AmountsOfTheInstallments: data.AmountsOfTheInstallments,
|
||||||
|
BookedPackages: data.BookedPackages,
|
||||||
|
AssignedEmployee: data.AssignedEmployee,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRequestError = (status) => {
|
||||||
|
if (status === 409) {
|
||||||
|
notificationApi["error"]({
|
||||||
|
message: t("crm.tabContent.request.duplicateCompanyError.message"),
|
||||||
|
description: t(
|
||||||
|
"crm.tabContent.request.duplicateCompanyError.description"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showUnkownErrorNotification(notificationApi, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (crmContext.openDrawerCustomerId.current === null) return;
|
||||||
|
|
||||||
|
formDealInfo
|
||||||
|
.validateFields()
|
||||||
|
.then((values) => {
|
||||||
|
if (crmContext.openDrawerCustomerId.current === "new") {
|
||||||
|
if (isOpen) {
|
||||||
|
formDealInfo.resetFields();
|
||||||
|
|
||||||
|
formDealInfo.setFieldsValue({
|
||||||
|
Pipeline: 1,
|
||||||
|
DealPhase: 1,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let changedFields = [];
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
if (values[key] !== undefined) {
|
||||||
|
changedFields.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check if something has changed (length 2 = only the pipeline and deal phase)
|
||||||
|
if (changedFields.length === 2) return;
|
||||||
|
|
||||||
|
let newCustomer = {};
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
if (values[key] !== undefined) {
|
||||||
|
newCustomer[key] = values[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
myFetch(`/crm/customer/create`, "POST", newCustomer)
|
||||||
|
.then(() => {
|
||||||
|
crmContext.openDrawerCustomerId.current = false;
|
||||||
|
handleCloseDrawer();
|
||||||
|
})
|
||||||
|
.catch((status) => handleRequestError(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
customerRequest();
|
||||||
|
} else {
|
||||||
|
let changedFields = [];
|
||||||
|
|
||||||
|
Object.keys(values).forEach((key) => {
|
||||||
|
if (
|
||||||
|
values[key] !== crmContext.currentDrawerCustomerRef.current[key]
|
||||||
|
) {
|
||||||
|
changedFields.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// check if something has changed
|
||||||
|
if (changedFields.length > 0) {
|
||||||
|
// only updated changed fields
|
||||||
|
const updatedCustomer = {};
|
||||||
|
|
||||||
|
changedFields.forEach((key) => {
|
||||||
|
updatedCustomer[key] = values[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
myFetch(
|
||||||
|
`/crm/customer/update/${crmContext.openDrawerCustomerId.current}`,
|
||||||
|
"POST",
|
||||||
|
updatedCustomer
|
||||||
|
)
|
||||||
|
.then(() => handleCloseDrawer())
|
||||||
|
.catch((status) => handleRequestError(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
|
const handleCustomerRequest = () => customerRequest();
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
wsConnectionCustomEventName,
|
||||||
|
handleCustomerRequest
|
||||||
|
);
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
document.removeEventListener(
|
||||||
|
wsConnectionCustomEventName,
|
||||||
|
handleCustomerRequest
|
||||||
|
);
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const handleCloseDrawer = () => {
|
||||||
|
crmContext.openDrawerCustomerId.current = null;
|
||||||
|
crmContext.currentDrawerCustomerRef.current = null;
|
||||||
|
crmContext.changedDrawerCustomerFieldsRef.current = [];
|
||||||
|
|
||||||
|
formDealInfo.resetFields();
|
||||||
|
|
||||||
|
setActiveTab(tabItems[0].key);
|
||||||
|
};
|
||||||
|
|
||||||
|
const title =
|
||||||
|
crmContext.currentDrawerCustomer === null
|
||||||
|
? "loading..."
|
||||||
|
: `${crmContext.currentDrawerCustomer?.FirstName} ${crmContext.currentDrawerCustomer?.LastName}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Drawer
|
||||||
|
title={title}
|
||||||
|
placement="right"
|
||||||
|
open={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
width={720}
|
||||||
|
extra={
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
onClose();
|
||||||
|
handleCloseDrawer();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("crm.buttonUndo")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Tabs
|
||||||
|
activeKey={activeTab}
|
||||||
|
onChange={(activeKey) => setActiveTab(activeKey)}
|
||||||
|
items={tabItems}
|
||||||
|
centered
|
||||||
|
/>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Content({ children }) {
|
||||||
|
return (
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col xs={24} sm={12}>
|
||||||
|
{children[0]}
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={12}>
|
||||||
|
{children[1]}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function CollapseContainer({ children, label }) {
|
||||||
|
return (
|
||||||
|
<Collapse
|
||||||
|
defaultActiveKey="1"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: "1",
|
||||||
|
label: label,
|
||||||
|
children: children,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabContentDealInfo({ form }) {
|
||||||
|
const pipeline = Form.useWatch("Pipeline", form);
|
||||||
|
|
||||||
|
const FormItem = ({ name, label }) => (
|
||||||
|
<Form.Item name={name} label={t(label)}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
|
||||||
|
const ContentBlock = ({ items }) => {
|
||||||
|
// Split items into chunks of two
|
||||||
|
const chunks = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i += 2) {
|
||||||
|
chunks.push(items.slice(i, i + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render a Content component for each chunk
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{chunks.map((chunk, index) => (
|
||||||
|
<Content key={index}>
|
||||||
|
{chunk.map((item) => (
|
||||||
|
<FormItem key={item.name} {...item} />
|
||||||
|
))}
|
||||||
|
</Content>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CollapseContainerBlock = ({ label, items }) => (
|
||||||
|
<CollapseContainer label={t(label)}>
|
||||||
|
<ContentBlock items={items} />
|
||||||
|
</CollapseContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MySupsenseFallback>
|
||||||
|
<Form form={form} layout="vertical">
|
||||||
|
<Space direction="vertical" style={{ display: "flex" }}>
|
||||||
|
<CollapseContainer
|
||||||
|
label={t("crm.tabContent.dealInfo.collapseDealStatus.label")}
|
||||||
|
>
|
||||||
|
<Content>
|
||||||
|
<Form.Item
|
||||||
|
name="Pipeline"
|
||||||
|
label={t("crm.tabContent.dealInfo.collapseDealStatus.pipeline")}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
label: t("crm.dmcPipeline.pageTitle"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
label: t("crm.setterCloser.pageTitle"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="DealPhase"
|
||||||
|
label={t(
|
||||||
|
"crm.tabContent.dealInfo.collapseDealStatus.dealPhase"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={t(
|
||||||
|
pipeline === 1
|
||||||
|
? "crm.dmcPipeline.segmentedOptions"
|
||||||
|
: "crm.setterCloser.segmentedOptions",
|
||||||
|
{ returnObjects: true }
|
||||||
|
).map((item, index) => {
|
||||||
|
return {
|
||||||
|
value: index + 1,
|
||||||
|
label: item,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Content>
|
||||||
|
</CollapseContainer>
|
||||||
|
|
||||||
|
<CollapseContainerBlock
|
||||||
|
label="crm.tabContent.dealInfo.collapseMasterDataOfContact.label"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
name: "FirstName",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.firstName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LastName",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.lastName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Telephone",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.telephone",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Email",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.email",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Company",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.company",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ZipCode",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.zipCode",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Address",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "City",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.city",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Country",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.country",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "FederalState",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.federalState",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Website",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.website",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LeadOrigin",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseMasterDataOfContact.leadOrigin",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CollapseContainerBlock
|
||||||
|
label="crm.tabContent.dealInfo.collapseSetterInfo.label"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
name: "NumberOfEmployees",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseSetterInfo.numberOfEmployees",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumberOfJobsSearchedFor",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseSetterInfo.numberOfJobsSearchedFor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JobTitle",
|
||||||
|
label: "crm.tabContent.dealInfo.collapseSetterInfo.jobTitle",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumberOfEmployeesRequired",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseSetterInfo.numberOfEmployeesRequired",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "HowLongHadHeBeenSearching",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseSetterInfo.howLongHadHeBeenSearching",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Turnover",
|
||||||
|
label: "crm.tabContent.dealInfo.collapseSetterInfo.turnover",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CollapseContainerBlock
|
||||||
|
label="crm.tabContent.dealInfo.collapseDealProperties.label"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
name: "DateOfcompletion",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.dateOfcompletion",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OrderVolume",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.orderVolume",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumberOfInstallments",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.numberOfInstallments",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "AmountsOfTheInstallments",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.amountsOfTheInstallments",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "BookedPackages",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.bookedPackages",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "AssignedEmployee",
|
||||||
|
label:
|
||||||
|
"crm.tabContent.dealInfo.collapseDealProperties.assignedEmployee",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Form>
|
||||||
|
</MySupsenseFallback>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabContentActivities() {
|
||||||
|
return (
|
||||||
|
<MySupsenseFallback>
|
||||||
|
<div>Coming soon</div>
|
||||||
|
</MySupsenseFallback>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabContentNotes({ notes }) {
|
||||||
|
const crmContext = useCrmContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MySupsenseFallback>
|
||||||
|
<MDXEditor
|
||||||
|
key={crmContext.currentDrawerCustomer?.Id}
|
||||||
|
className="mdx-editor"
|
||||||
|
markdown={notes}
|
||||||
|
onChange={(value) => {
|
||||||
|
crmContext.setCurrentDrawerCustomer({
|
||||||
|
...crmContext.currentDrawerCustomer,
|
||||||
|
Notes: value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
plugins={[
|
||||||
|
listsPlugin(),
|
||||||
|
quotePlugin(),
|
||||||
|
headingsPlugin(),
|
||||||
|
linkPlugin(),
|
||||||
|
linkDialogPlugin(),
|
||||||
|
tablePlugin(),
|
||||||
|
thematicBreakPlugin(),
|
||||||
|
frontmatterPlugin(),
|
||||||
|
markdownShortcutPlugin(),
|
||||||
|
toolbarPlugin({
|
||||||
|
toolbarContents: () => (
|
||||||
|
<>
|
||||||
|
<UndoRedo />
|
||||||
|
<BoldItalicUnderlineToggles />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</MySupsenseFallback>
|
||||||
|
);
|
||||||
|
}
|
|
@ -91,8 +91,10 @@ export const Constants = {
|
||||||
CONSOLES: "/consoles",
|
CONSOLES: "/consoles",
|
||||||
ROBOTICS_ROBOTS: "/robotics/robots",
|
ROBOTICS_ROBOTS: "/robotics/robots",
|
||||||
CRM: "/crm/",
|
CRM: "/crm/",
|
||||||
|
CRM_TEST: "/crm/test",
|
||||||
},
|
},
|
||||||
CRM_TYPE: {
|
CRM_TYPE: {
|
||||||
|
TEST_CUSTOMERS: "test-customers",
|
||||||
CUSTOMERS: "customers",
|
CUSTOMERS: "customers",
|
||||||
DMC_PIPELINE: "dmc-pipeline",
|
DMC_PIPELINE: "dmc-pipeline",
|
||||||
SETTER_CLOSER: "setter-closer",
|
SETTER_CLOSER: "setter-closer",
|
||||||
|
|
Loading…
Reference in New Issue