frontPanel/src/pages/IntegrationsPage/IntegrationsModal/Bitrix/useBitrixIntegration.ts
2025-12-06 09:30:01 +03:00

447 lines
14 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 { useEffect, useState } from "react";
import { enqueueSnackbar } from "notistack";
import type { TagKeys, SelectedTags, QuestionKeys, SelectedQuestions, MinifiedData } from "./types";
import {
AccountResponse,
getIntegrationRules,
getPipelines,
getSteps,
getTags,
getUsers,
getAccount,
FieldsRule,
getFields,
connectBitrix,
} from "@/api/bitrixIntegration";
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import { UntypedQuizQuestion } from "@/model/questionTypes/shared";
const SIZE = 25;
interface Props {
isModalOpen: boolean;
isTryRemoveAccount: boolean;
quizID: number;
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion)[]
}
const FCTranslate = {
"name": "имя",
"email": "почта",
"phone": "телефон",
"text": "номер",
"address": "адрес",
}
let isReadyGetPipeline = true;
let isReadyGetPipelineStep = true;
let isReadyGetUsers = true;
let isReadyGetTags = true;
let isReadyGetFields = true;
export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, questions }: Props) => {
const [isLoadingPage, setIsLoadingPage] = useState<boolean>(true);
const [firstRules, setFirstRules] = useState<boolean>(false);
const [accountInfo, setAccountInfo] = useState<AccountResponse | null>(null);
const [leadFlag, setLeadFlag] = useState<boolean>(false);
const [arrayOfPipelines, setArrayOfPipelines] = useState<MinifiedData[]>([]);
const [arrayOfPipelinesSteps, setArrayOfPipelinesSteps] = useState<MinifiedData[]>([]);
const [fullArrayOfPipelinesSteps, setFullArrayOfPipelinesSteps] = useState<any[]>([]);
const [arrayOfUsers, setArrayOfUsers] = useState<MinifiedData[]>([]);
const [arrayOfTags, setArrayOfTags] = useState<MinifiedData[]>([]);
const [arrayOfFields, setArrayOfFields] = useState<MinifiedData[]>([]);
const [selectedPipeline, setSelectedPipeline] = useState<string | null>(null);
const [selectedPipelineStep, setSelectedPipelineStep] = useState<string | null>(null);
const [selectedDealUser, setSelectedDealPerformer] = useState<string | null>(null);
const [selectedCurrentFields, setSelectedCurrentFields] = useState<MinifiedData[]>([]);
const [questionsBackend, setQuestionsBackend] = useState<FieldsRule>({} as FieldsRule);
const [selectedTags, setSelectedTags] = useState<SelectedTags>({
Lead: [],
Contact: [],
Company: [],
Customer: [],
});
const [selectedQuestions, setSelectedQuestions] = useState<SelectedQuestions>({
lead: [],
company: [],
contact: [],
deal: [],
CRM_INVOICE: [],
CRM_SMART_INVOICE: [],
CRM_QUOTE: [],
CRM_REQUISITE: [],
});
const [pageOfPipelines, setPageOfPipelines] = useState(1);
const [pageOfPipelinesSteps, setPageOfPipelinesSteps] = useState(1);
const [pageOfUsers, setPageOfUsers] = useState(1);
const [pageOfTags, setPageOfTags] = useState(1);
const [pageOfFields, setPageOfFields] = useState(1);
const leadFlagHC = (s:boolean) => {
setLeadFlag(s)
};
const selectedPipelineHC = (id:string | null) => {
setSelectedPipeline(id);
isReadyGetPipelineStep = true;
setPageOfPipelinesSteps(1);
}
// useEffect(() => {
// (async () => {
// const API_URL = `https://penadigitaltech.bitrix24.ru`;
// try {
// const response = await makeRequest<void, { link: string }>({
// method: "POST",
// url: `${API_URL}/account`,
// useToken: true,
// withCredentials: true,
// body: {
// "client_bitrix_url": "penadigitaltech.bitrix24.ru"
// }
// });
// window.open(response.link, "_blank");
// } catch (nativeError) {
// return [null, `Не удалось подключить аккаунт. `];
// }
// })()
// }, [isModalOpen])
useEffect(() => {
const fetchAccountRules = async () => {
setIsLoadingPage(true);
const [account, accountError] = await getAccount();
if (accountError) {
if (!accountError.includes("Not Found")) enqueueSnackbar(accountError);
setAccountInfo(null);
}
if (account) {
setAccountInfo(account);
}
const [settingsResponse, rulesError] = await getIntegrationRules(quizID.toString());
if (rulesError) {
if (rulesError === "first") setFirstRules(true);
if (!rulesError.includes("Not Found") && !rulesError.includes("first")) enqueueSnackbar(rulesError);
}
if (settingsResponse) {
if (settingsResponse.PipelineID) selectedPipelineHC(settingsResponse.PipelineID.toString());
if (settingsResponse.StepID) setSelectedPipelineStep(settingsResponse.StepID.toString());
if (settingsResponse.PerformerID) setSelectedDealPerformer(settingsResponse.PerformerID.toString());
console.log("settingsResponse")
console.log(settingsResponse)
setLeadFlag(settingsResponse.LeadFlag)
if (Boolean(settingsResponse.FieldsRule) && Object.keys(settingsResponse?.FieldsRule).length > 0) {
const gottenQuestions = { ...selectedQuestions };
setQuestionsBackend(settingsResponse.FieldsRule);
for (let key in settingsResponse.FieldsRule) {
if (
settingsResponse.FieldsRule[key as QuestionKeys] !== null
) {
const gottenList = settingsResponse.FieldsRule[key as QuestionKeys];
if (gottenList !== null) {
Object.keys(gottenList.QuestionID).forEach((qId) => {
const q = questions.find(e => e.backendId === Number(qId)) || {}
if (gottenQuestions[key as QuestionKeys] === undefined) gottenQuestions[key as QuestionKeys] = []
gottenQuestions[key as QuestionKeys].push({
id: qId,
title: q.title,
entity: key,
})
})
}
if (key === "Contact") {
const MAP = settingsResponse.FieldsRule[key as QuestionKeys].ContactRuleMap
const list = []
for (let key in MAP) {
list.push({
id: key,
title: FCTranslate[key],
entity: "Contact",
bitrixId: MAP[key].toString(),
})
}
setSelectedCurrentFields(list)
}
}
}
setSelectedQuestions(gottenQuestions);
}
if (Boolean(settingsResponse.TagsToAdd) && Object.keys(settingsResponse.TagsToAdd).length > 0) {
const gottenTags = { ...selectedTags };
for (let key in settingsResponse.TagsToAdd) {
const gottenList = settingsResponse.TagsToAdd[key as TagKeys];
if (gottenList !== null && Array.isArray(gottenList)) {
gottenTags[key as TagKeys] = gottenList.map((e) => e.toString());
}
}
setSelectedTags(gottenTags);
}
setFirstRules(false);
}
setIsLoadingPage(false);
};
fetchAccountRules();
}, [isModalOpen, isTryRemoveAccount]);
useEffect(() => {
const transletedQuestions = {...selectedQuestions}
Object.keys(selectedQuestions)?.forEach((column) => {
selectedQuestions[column].forEach((minifiedData) => {
const q = questions.find(e => e.backendId === Number(minifiedData.id)) || {};
transletedQuestions[column].push({
...minifiedData,
title: q.title || transletedQuestions[column].title
})
})
})
setSelectedQuestions(transletedQuestions)
}, [questions])
useEffect(() => {
if (isReadyGetPipeline) {
getPipelines({
page: pageOfPipelines,
size: SIZE,
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedPipelines: MinifiedData[] = [];
response.items.forEach((step) => {
minifiedPipelines.push({
id: step.bitrixID.toString(),
title: step.name || "Нет названия",
});
});
setArrayOfPipelines((prevItems) => [...prevItems, ...minifiedPipelines]);
setPageOfPipelinesSteps(1);
} else {
isReadyGetPipeline = false
}
});
}
}, [pageOfPipelines]);
useEffect(() => {
if (isReadyGetPipelineStep && selectedPipeline !== null) {
const oldData = pageOfPipelinesSteps === 1 ? [] : arrayOfPipelinesSteps;
const oldFullData = pageOfPipelinesSteps === 1 ? [] : fullArrayOfPipelinesSteps;
getSteps({
page: pageOfPipelinesSteps,
size: SIZE,
pipelineId: Number(selectedPipeline),
}).then(([response]) => {
if (response && response.items !== null) {
// Фильтруем только нужные элементы
const filteredItems = response.items.filter(item =>
item.entityID === "STATUS" ||
item.entityID === "SOURCE" ||
(typeof item.entityID === 'string' && item.entityID.startsWith("DEAL_STAGE"))
);
// Минифицируем отфильтрованные данные
const minifiedSteps: MinifiedData[] = filteredItems.map((step) => ({
id: step.bitrixID.toString(),
title: step.name,
entity: step.entityID
}));
// Обновляем массивы
setArrayOfPipelinesSteps([...oldData, ...minifiedSteps]);
setFullArrayOfPipelinesSteps([...oldFullData, ...filteredItems]);
} else {
// Если нет данных, отключаем дальнейшие запросы
isReadyGetPipelineStep = false;
}
}).catch(error => {
console.error("Ошибка при получении шагов:", error);
isReadyGetPipelineStep = false;
});
}
}, [selectedPipeline, pageOfPipelinesSteps]);
useEffect(() => {
if (isReadyGetUsers) {
getUsers({
page: pageOfUsers,
size: SIZE,
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedUsers: MinifiedData[] = [];
response.items.forEach((step) => {
minifiedUsers.push({
id: step.bitrixUserID.toString(),
title: step.name || "Нет имени",
});
});
setArrayOfUsers((prevItems) => [...prevItems, ...minifiedUsers]);
} else {
isReadyGetUsers = false
}
});
}
}, [pageOfUsers]);
// useEffect(() => {
// if (isReadyGetTags) {
// getTags({
// page: pageOfTags,
// size: SIZE,
// }).then(([response]) => {
// if (response && response.items !== null) {
// const minifiedTags: MinifiedData[] = [];
// response.items.forEach((step) => {
// minifiedTags.push({
// id: step.BitrixID.toString(),
// title: step.Name,
// entity:
// step.Entity === "leads"
// ? "Lead"
// : step.Entity === "contacts"
// ? "Contact"
// : step.Entity === "companies"
// ? "Company"
// : "Customer",
// });
// });
// setArrayOfTags((prevItems) => [...prevItems, ...minifiedTags]);
// } else {
// isReadyGetTags = false
// }
// });
// }
// }, [pageOfTags]);
useEffect(() => {
if (isReadyGetFields) {
getFields({
page: pageOfFields,
size: 1000,
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedTags: MinifiedData[] = [];
console.log("fields: ")
console.log(response.items)
const entityMap = {
'CRM_LEAD': 'lead',
'CRM_DEAL': 'deal',
'CRM_COMPANY': 'company',
'CRM_CONTACT': 'contact'
};
response.items.forEach((field) => {
console.log("поле: ")
console.log(field)
const entity = entityMap[field.entityID];
if (entity) {
minifiedTags.push({
id: field.bitrixID.toString(),
title: field.editFromLabel,
entity: entity,
});
}
});
setArrayOfFields((prevItems) => [...prevItems, ...minifiedTags]);
}
});
} else {
isReadyGetFields = false
}
}, [pageOfFields]);
useEffect(() => () => {
isReadyGetPipeline = true;
isReadyGetPipelineStep = true;
isReadyGetUsers = true;
isReadyGetTags = true;
isReadyGetFields = true;
}, [])
return {
isLoadingPage,
firstRules,
accountInfo,
arrayOfPipelines,
arrayOfPipelinesSteps,
arrayOfUsers,
arrayOfTags,
arrayOfFields,
selectedPipeline,
setSelectedPipeline: selectedPipelineHC,
selectedCurrentFields,
selectedPipelineStep,
setSelectedPipelineStep,
selectedDealUser,
setSelectedDealPerformer,
questionsBackend,
selectedTags,
setSelectedTags,
selectedQuestions,
setSelectedQuestions,
setPageOfPipelines: () => setPageOfPipelines(old => old + 1),
setPageOfPipelinesSteps: () => setPageOfPipelinesSteps(old => old + 1),
setPageOfUsers: () => setPageOfUsers(old => old + 1),
setPageOfTags: () => setPageOfTags(old => old + 1),
setPageOfFields: () => setPageOfFields(old => old + 1),
setSelectedCurrentFields,
leadFlag,
leadFlagHC,
fullArrayOfPipelinesSteps
};
};
import { makeRequest } from "@frontend/kitui";
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/bitrix`;
export const resetBitrixTagsFields = async () => {
let success = true
//Fields
try {
await makeRequest({
method: "PATCH",
url: `${API_URL}/fields`,
});
} catch (nativeError) {
success = false
}
//Tags
try {
await makeRequest({
method: "PATCH",
url: `${API_URL}/tags`,
});
} catch (nativeError) {
success = false
}
if (success) {
enqueueSnackbar("Данные обновятся через 5-30 минут")
} else {
enqueueSnackbar("Не удалось обновить данные")
}
}