This commit is contained in:
Nastya 2025-12-03 00:28:36 +03:00
parent e734e8b28b
commit 4997179b75
23 changed files with 740 additions and 381 deletions

@ -1,3 +1,4 @@
1.0.15 _ 2025-12-03 _ Merge branch 'pin' into staging
1.0.14 _ 2025-10-20 _ логика overtime для публички
1.0.13 _ 2025-10-18 _ Визуал utm + логика
1.0.12 _ 2025-10-12 _ ютм с дизайном и беком, но без логики

@ -16,13 +16,10 @@ const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/bitrix`;
export type AccountResponse = {
id: number;
accountID: string;
amoID: number;
name: string;
bitrixID: number;
deleted: boolean;
createdAt: string;
subdomain: string;
country: string;
driveURL: string;
stale: boolean;
};
@ -56,10 +53,13 @@ export function useBitrixAccount() {
export const connectBitrix = async (): Promise<[string | null, string?]> => {
try {
const response = await makeRequest<void, { link: string }>({
const response = await makeRequest<{client_bitrix_url: string}, { link: string }>({
method: "POST",
url: `${API_URL}/account`,
useToken: true,
body: {
client_bitrix_url: 'penadigitaltech.bitrix24.ru'
},
withCredentials: true,
});
return [response.link];
@ -125,16 +125,18 @@ export const getTags = async ({ page, size }: PaginationRequest): Promise<[TagsR
export type User = {
id: number;
amoID: number;
accountID: string;
bitrixUserID: string;
name: string;
lastName: string;
secondName: string;
title: string;
email: string;
role: number;
group: number;
uf_department: [ number ];
deleted: boolean;
createdAt: string;
amoUserID: number;
workPosition: string;
};
export type UsersResponse = {
count: number;
items: User[];
@ -157,13 +159,16 @@ export const getUsers = async ({ page, size }: PaginationRequest): Promise<[User
export type Step = {
ID: number;
AmoID: number;
PipelineID: number;
AccountID: number;
Name: string;
Color: string;
Deleted: boolean;
CreatedAt: number;
accountID: string;
bitrixID: string;
entityID: string;
statusID: string;
name: string;
nameInit: string;
color: string;
pipelineID: number;
deleted: boolean;
createdAt: number;
};
export type StepsResponse = {
@ -192,12 +197,12 @@ export const getSteps = async ({
export type Pipeline = {
ID: number;
AmoID: number;
AccountID: number;
Name: string;
IsArchive: boolean;
Deleted: boolean;
CreatedAt: number;
bitrixID: number;
accountID: number;
name: string;
entityTypeId: boolean;
deleted: boolean;
createdAt: number;
};
export type PipelinesResponse = {
@ -310,15 +315,16 @@ export type CustomField = {
};
export type Field = {
ID: number;
AmoID: number;
Code: string;
AccountID: number;
Name: string;
Entity: string;
Type: string;
Deleted: boolean;
CreatedAt: number;
accountID: string;
bitrixID: string;
entityID: string;
fieldName: string;
editFromLabel: string;
fieldType: string;
deleted: boolean;
createdAt: number;
};
export type CustomFieldsResponse = {
count: number;
items: CustomField[];

@ -24,6 +24,8 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
console.log("CustomRadioGroup")
console.log(items)
const currentItem =
(selectedItemId !== null && selectedItemId.length > 0) ?
items.find((item) => item.id === selectedItemId) || null

@ -26,6 +26,7 @@ export const CustomSelect: FC<CustomSelectProps> = ({ items, selectedItemId, set
const currentItem = useMemo(() => items.find((item) => item.id === selectedItemId) || null, [selectedItemId, items]);
const menuItems = useMemo(() => {
if (items.length !== 0) {
return items.map((item) => (

@ -113,21 +113,23 @@ export const useAmoIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, que
) {
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)) || {}
console.log("gottenList-----")
console.log(gottenList)
// 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] = []
// if (gottenQuestions[key as QuestionKeys] === undefined) gottenQuestions[key as QuestionKeys] = []
gottenQuestions[key as QuestionKeys].push({
id: qId,
title: q.title,
entity: key,
// gottenQuestions[key as QuestionKeys].push({
// id: qId,
// title: q.title,
// entity: key,
})
})
// })
// })
}
// }
if (key === "Contact") {
const MAP = settingsResponse.FieldsRule[key as QuestionKeys].ContactRuleMap

@ -4,13 +4,13 @@ import { FC } from "react";
import { AccountResponse } from "@/api/bitrixIntegration";
import AccountSetting from "@icons/AccountSetting";
type AmoAccountInfoProps = {
type BitrixAccountInfoProps = {
handleNextStep: () => void;
accountInfo: AccountResponse | null;
toChangeAccount: () => void;
};
export const AccountInfo: FC<AmoAccountInfoProps> = ({ handleNextStep, accountInfo, toChangeAccount }) => {
export const AccountInfo: FC<BitrixAccountInfoProps> = ({ handleNextStep, accountInfo, toChangeAccount }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -119,11 +119,9 @@ export const AccountInfo: FC<AmoAccountInfoProps> = ({ handleNextStep, accountIn
>
1 шаг
</Typography>
{infoItem("Amo ID", accountInfo?.amoID)}
{infoItem("Имя аккаунта", accountInfo?.name)}
{infoItemLink("ЛК в amo", `https://${accountInfo?.subdomain}/dashboard/`)}
{infoItemLink("Профиль пользователя в amo", `https://${accountInfo?.subdomain}/settings/users/`)}
{infoItem("Страна пользователя", accountInfo?.country)}
{infoItem("Bitrix ID", accountInfo?.bitrixID)}
{/* {infoItemLink("ЛК в bitrix", `https://${accountInfo?.subdomain}/dashboard/`)}
{infoItemLink("Профиль пользователя в bitrix", `https://${accountInfo?.subdomain}/settings/users/`)} */}
</Box>
<Box>

@ -22,7 +22,7 @@ type IntegrationStep1Props = {
// password: string().required("Поле обязательно").min(8, "Минимум 8 символов"),
// });
export const AmoLogin: FC<IntegrationStep1Props> = ({ handleNextStep }) => {
export const BitrixLogin: FC<IntegrationStep1Props> = ({ handleNextStep }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));

@ -1,5 +1,5 @@
import { connectBitrix } from "@/api/bitrixIntegration";
import { setTryShowAmoTokenExpiredDialog } from "@/stores/uiTools/actions";
import { setTryShowBitrixTokenExpiredDialog } from "@/stores/uiTools/actions";
import { useUiTools } from "@/stores/uiTools/store";
import CustomCheckbox from "@/ui_kit/CustomCheckbox";
import { Box, Button, Dialog, Typography, useTheme } from "@mui/material";
@ -9,17 +9,17 @@ import { useLocation } from "react-router-dom";
const HIDE_DIALOG_EXPIRATION_PERIOD = 24 * 60 * 60 * 1000;
interface Props {
isAmoTokenExpired: boolean;
isBitrixTokenExpired: boolean;
}
export default function AmoTokenExpiredDialog({ isAmoTokenExpired }: Props) {
export default function BitrixTokenExpiredDialog({ isBitrixTokenExpired }: Props) {
const theme = useTheme();
const tryShowAmoTokenExpiredDialog = useUiTools((state) => state.tryShowAmoTokenExpiredDialog);
const tryShowBitrixTokenExpiredDialog = useUiTools((state) => state.tryShowBitrixTokenExpiredDialog);
const [isHideDialogForADayChecked, setIsHideDialogForADayChecked] = useState<boolean>(false);
// const { hash, pathname, search } = useLocation();
const location = useLocation();
const onAmoClick = async () => {
const onBitrixClick = async () => {
const [url, error] = await connectBitrix();
if (url && !error) {
window.open(url, "_blank");
@ -29,19 +29,19 @@ export default function AmoTokenExpiredDialog({ isAmoTokenExpired }: Props) {
function handleDialogClose() {
if (isHideDialogForADayChecked) {
const expirationDate = Date.now() + HIDE_DIALOG_EXPIRATION_PERIOD;
localStorage.setItem("hideAmoTokenExpiredDialogExpirationTime", expirationDate.toString());
localStorage.setItem("hideBitrixTokenExpiredDialogExpirationTime", expirationDate.toString());
}
setTryShowAmoTokenExpiredDialog(false);
setTryShowBitrixTokenExpiredDialog(false);
}
useEffect(() => {
setTryShowAmoTokenExpiredDialog(true);
setTryShowBitrixTokenExpiredDialog(true);
}, [location]);
return (
<Dialog
open={isAmoTokenExpired && tryShowAmoTokenExpiredDialog && location.pathname !== "/"}
open={isBitrixTokenExpired && tryShowBitrixTokenExpiredDialog && location.pathname !== "/"}
onClose={handleDialogClose}
PaperProps={{
sx: {
@ -96,7 +96,7 @@ export default function AmoTokenExpiredDialog({ isAmoTokenExpired }: Props) {
</Button>
<Button
variant="contained"
onClick={onAmoClick}
onClick={onBitrixClick}
sx={{
flex: "1 0 0",
}}

@ -17,7 +17,7 @@ type Props = {
title: string;
desc: string;
toSettings: () => void;
}
};
onScrollUsers: () => void;
};
@ -36,39 +36,37 @@ export const DealPerformers: FC<Props> = ({
return (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
overflow: "auto",
flexGrow: 1,
}}
>
<Box sx={{ width: "100%", zIndex: 3 }}>
<ModalTitle
{...titleProps}
/>
<CustomSelect
items={users}
selectedItemId={selectedDealUser}
setSelectedItem={setSelectedDealPerformer}
handleScroll={onScrollUsers}
/>
</Box>
<Box
sx={{
marginTop: "auto",
alignSelf: "end",
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
overflow: "auto",
flexGrow: 1,
}}
>
<StepButtonsBlock
onLargeBtnClick={handleNextStep}
onSmallBtnClick={handlePrevStep}
/>
<Box sx={{ width: "100%", zIndex: 3 }}>
<ModalTitle {...titleProps} />
<CustomSelect
items={users}
selectedItemId={selectedDealUser}
setSelectedItem={setSelectedDealPerformer}
handleScroll={onScrollUsers}
/>
</Box>
<Box
sx={{
marginTop: "auto",
alignSelf: "end",
}}
>
<StepButtonsBlock
onLargeBtnClick={handleNextStep}
onSmallBtnClick={handlePrevStep}
/>
</Box>
</Box>
</Box>
</>
);
};

@ -15,13 +15,14 @@ type Props = {
setSelectedDealPerformer: (value: string | null) => void;
selectedStep: string | null;
setSelectedStep: (value: string | null) => void;
leadFlag: boolean;
titleProps: {
step: number;
title: string;
desc: string;
toSettings: () => void;
}
};
onScroll: () => void;
onScrollUsers: () => void;
};
@ -36,17 +37,18 @@ export const PipelineSteps: FC<Props> = ({
setSelectedStep,
onScroll,
onScrollUsers,
leadFlag,
handlePrevStep,
handleNextStep,
titleProps
titleProps,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
console.log("leadFlag")
console.log(leadFlag)
return (
<>
<Box
@ -65,11 +67,10 @@ export const PipelineSteps: FC<Props> = ({
overflow: "auto",
zIndex: 3,
width: "100%",
}}>
}}
>
<Box sx={{ width: "100%", zIndex: 3 }}>
<ModalTitle
{...titleProps}
/>
<ModalTitle {...titleProps} />
<CustomSelect
items={users}
selectedItemId={selectedDealUser}
@ -85,7 +86,7 @@ export const PipelineSteps: FC<Props> = ({
}}
>
<CustomRadioGroup
items={steps}
items={leadFlag ? steps : steps.filter(step => step.entity !== "STATUS")}
selectedItemId={selectedStep}
setSelectedItem={setSelectedStep}
handleScroll={onScroll}

@ -8,7 +8,7 @@ import { diffArr } from "..";
import { DataConstrictor } from "../Components/DataConstrictor";
import { ModalTitle } from "../ModalTitle";
import { StepButtonsBlock } from "../StepButtonsBlock";
import { resetBitrixTagsFields } from "../useAmoIntegration";
import { resetBitrixTagsFields } from "../useBitrixIntegration";
type Props = {
selectedCurrentFields: MinifiedData[] | [];
@ -39,11 +39,11 @@ const FCTranslate = {
"text": "номер",
"address": "адрес",
}
export const AmoQuestions: FC<Props> = ({
export const BitrixQuestions: FC<Props> = ({
selectedCurrentFields,
questionsItems,
fieldsItems,
selectedQuestions = [],
selectedQuestions = {},
handleAddQuestion,
handlePrevStep,
handleNextStep,
@ -53,17 +53,54 @@ export const AmoQuestions: FC<Props> = ({
onScroll,
titleProps,
}) => {
if (!selectedQuestions.hasOwnProperty('Contact')) {
selectedQuestions.Contact = []
console.log("---------------------------------------------------------------------")
console.log(
{
selectedCurrentFields,
questionsItems,
fieldsItems,
selectedQuestions,
handleAddQuestion,
handlePrevStep,
handleNextStep,
openDelete,
FieldsAllowedFC,
setSelectedCurrentFields,
onScroll,
titleProps,
}
)
// "lead": "Лид",
// "company": "Компания",
// "contact": "Контакт",
// "deal": "Сделка",
// "CRM_INVOICE": "Счёт (старый)",
// "CRM_SMART_INVOICE": "Cчёт (новый)",
// "CRM_QUOTE": "Предложение",
// "CRM_REQUISITE": "Реквизит"
if (!selectedQuestions.hasOwnProperty('lead')) {
selectedQuestions.lead = []
}
if (!selectedQuestions.hasOwnProperty('Customer')) {
selectedQuestions.Customer = []
if (!selectedQuestions.hasOwnProperty('company')) {
selectedQuestions.company = []
}
if (!selectedQuestions.hasOwnProperty('Company')) {
selectedQuestions.Company = []
if (!selectedQuestions.hasOwnProperty('contact')) {
selectedQuestions.contact = []
}
if (!selectedQuestions.hasOwnProperty('Lead')) {
selectedQuestions.Lead = []
if (!selectedQuestions.hasOwnProperty('deal')) {
selectedQuestions.deal = []
}
if (!selectedQuestions.hasOwnProperty('CRM_INVOICE')) {
selectedQuestions.CRM_INVOICE = []
}
if (!selectedQuestions.hasOwnProperty('CRM_SMART_INVOICE')) {
selectedQuestions.CRM_SMART_INVOICE = []
}
if (!selectedQuestions.hasOwnProperty('CRM_QUOTE')) {
selectedQuestions.CRM_QUOTE = []
}
if (!selectedQuestions.hasOwnProperty('CRM_REQUISITE')) {
selectedQuestions.CRM_REQUISITE = []
}
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -95,7 +132,7 @@ export const AmoQuestions: FC<Props> = ({
id: selectedQuestion,
title: questionsItems.find(e => e.id === selectedQuestion)?.title || FCTranslate[selectedQuestion],
entity: activeScope,
amoId: selectedField,
bitrixId: selectedField,
})
setSelectedCurrentFields(newArray);
};
@ -117,10 +154,14 @@ export const AmoQuestions: FC<Props> = ({
};
const SCFworld = (() => {
const obj = {
Lead: [],
Company: [],
Customer: [],
Contact: []
lead: [],
company: [],
contact: [],
deal: [],
// CRM_INVOICE: [],
// CRM_SMART_INVOICE: [],
// CRM_QUOTE: [],
// CRM_REQUISITE: [],
}
selectedCurrentFields.forEach((e) => {
if (!obj[e.entity]?.includes(e.id)) {
@ -216,10 +257,14 @@ export const AmoQuestions: FC<Props> = ({
items={[...questionsItems, ...FieldsAllowedFC]}
setActiveScope={setActiveScope}
selectedQuestions={{
Lead: [...selectedQuestions.Lead, ...SCFworld.Lead],
Company: [...selectedQuestions.Company, ...SCFworld.Company],
Customer: [...selectedQuestions.Customer, ...SCFworld.Customer],
Contact: [...selectedQuestions.Contact, ...SCFworld.Contact]
lead: [...selectedQuestions.lead, ...SCFworld.lead],
company: [...selectedQuestions.company, ...SCFworld.company],
contact: [...selectedQuestions.contact, ...SCFworld.contact],
deal: [...selectedQuestions.deal, ...SCFworld.deal],
// CRM_INVOICE: [...selectedQuestions.CRM_INVOICE, ...SCFworld.CRM_INVOICE],
// CRM_SMART_INVOICE: [...selectedQuestions.CRM_SMART_INVOICE, ...SCFworld.CRM_SMART_INVOICE],
// CRM_QUOTE: [...selectedQuestions.CRM_QUOTE, ...SCFworld.CRM_QUOTE],
// CRM_REQUISITE: [...selectedQuestions.CRM_REQUISITE, ...SCFworld.CRM_REQUISITE]
}}
setIsSelection={setIsSelection}
deleteHC={handleDelete}

@ -4,7 +4,7 @@ import { FC, useState } from "react";
import { MinifiedData, TagKeys } from "../types";
import { CurrentFields } from "./CurrentFields";
import { NewFields } from "./NewFields";
import { QuestionPair } from "./AmoQuestions";
import { QuestionPair } from "./BitrixQuestions";
import { diffArr } from "..";
type ItemsSelectionViewProps = {

@ -15,12 +15,20 @@ export const ItemForQuestions: FC<ItemProps> = ({ items, title, onAddBtnClick, d
const theme = useTheme();
const titleDictionary = {
Company: "Компания",
Lead: "Сделка",
Contact: "Контакты",
Customer: "Покупатели",
"lead": "Лид",
"company": "Компания",
"contact": "Контакт",
"deal": "Сделка",
// "CRM_INVOICE": "Счёт (старый)",
// "CRM_SMART_INVOICE": "Счёт (новый)",
// "CRM_QUOTE": "Предложение",
// "CRM_REQUISITE": "Реквизит"
// Company: "Компания",
// Lead: "Сделка",
// Contact: "Контакты",
// Customer: "Покупатели",
};
console.log("title: " + title)
const translatedTitle = titleDictionary[title];
const selectedOptions = data[title];
return (

@ -16,7 +16,7 @@ type SettingItemProps = {
selectedDealUser: string | null;
selectedStage: string | null;
selectedQuestions: SelectedQuestions;
selectedTags: SelectedTags;
leadFlag: boolean
};
export const SettingItem: FC<SettingItemProps> = ({
@ -29,7 +29,7 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedDealUser,
selectedStage,
selectedQuestions,
selectedTags,
leadFlag
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -42,31 +42,7 @@ export const SettingItem: FC<SettingItemProps> = ({
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
<SelectedParameter parameter={selectedFunnel} />
</>
);
}
if (step === 2) {
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
<SelectedParameter parameter={selectedStage} />
</>
);
}
if (step === 3) {
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
</>
);
}
if (step === 4) {
const isFilled = Object.values(selectedTags).some((array) => array.length > 0);
const status = isFilled ? "Заполнено" : "Не заполнено";
return (
<>
<Box>
<Typography
sx={{
color: theme.palette.grey2.main,
@ -76,7 +52,7 @@ export const SettingItem: FC<SettingItemProps> = ({
}}
display={"inline-block"}
>
Статус:
Выбранный этап сделки
</Typography>
<Typography
sx={{
@ -86,8 +62,33 @@ export const SettingItem: FC<SettingItemProps> = ({
}}
display={"inline"}
>
{status}
{leadFlag ? "Лид сделки" : "Дил сделки"}
</Typography>
</Box>
</>
);
}
if (step === 2) {
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
<SelectedParameter parameter={selectedFunnel} />
</>
);
}
if (step === 3) {
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
<SelectedParameter parameter={selectedStage} />
</>
);
}
if (step === 4) {
return (
<>
<ResponsiblePerson performer={selectedDealUser} />
</>
);
}
@ -130,7 +131,6 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedDealUser,
selectedStage,
selectedQuestions,
selectedTags,
]);
return (

@ -10,9 +10,9 @@ type AmoSettingsBlockProps = {
selectedStage: string | null;
selectedDealUser: string | null;
selectedQuestions: SelectedQuestions;
selectedTags: SelectedTags;
toBack: () => void
setStep: (step: number) => void
leadFlag: boolean
};
export const SettingsBlock: FC<AmoSettingsBlockProps> = ({
@ -21,9 +21,10 @@ export const SettingsBlock: FC<AmoSettingsBlockProps> = ({
selectedDealUser,
selectedStage,
selectedQuestions,
selectedTags,
// selectedTags,
toBack,
setStep,
leadFlag,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -64,13 +65,13 @@ export const SettingsBlock: FC<AmoSettingsBlockProps> = ({
{stepTitles &&
stepTitles.map((title, index) => (
<SettingItem
leadFlag={leadFlag}
step={index+1}
title={title}
selectedDealUser={selectedDealUser}
selectedFunnel={selectedFunnel}
selectedStage={selectedStage}
selectedQuestions={selectedQuestions}
selectedTags={selectedTags}
setStep={setStep}
/>

@ -1,4 +1,4 @@
import { useMemo, useState } from "react"
import { useMemo, useState } from "react";
import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box, Skeleton } from "@mui/material";
import { useQuestions } from "@/stores/questions/hooks";
import { redirect } from "react-router-dom";
@ -8,28 +8,28 @@ import CloseIcon from "@mui/icons-material/Close";
import { RemoveAccount } from "./RemoveAccount";
import { DeleteTagQuestion } from "./DeleteTagQuestion";
import { AmoLogin } from "./AmoLogin";
import { BitrixLogin } from "./BitrixLogin";
import { Pipelines } from "./Pipelines";
import { PipelineSteps } from "./PipelineSteps";
import { DealPerformers } from "./DealPerformers";
import { AmoTags } from "./Tags/AmoTags";
import { AmoQuestions } from "./Questions/AmoQuestions";
import { СhoosePerson } from "./СhoosePerson";
import { BitrixQuestions } from "./Questions/BitrixQuestions";
import { ModalTitle } from "./ModalTitle";
import { SettingsBlock } from "./SettingsBlock/SettingsBlock";
import { AccountInfo } from "./AccountInfo";
import { MinifiedData, QuestionKeys, TagKeys, TagQuestionHC } from "./types";
import { Quiz } from "@/model/quiz/quiz";
import { AccountResponse, setIntegrationRules, updateIntegrationRules } from "@/api/integration";
import { AccountResponse, setIntegrationRules, updateIntegrationRules } from "@/api/bitrixIntegration";
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import { UntypedQuizQuestion } from "@/model/questionTypes/shared";
const FCTranslate = {
"name": "имя",
"email": "почта",
"phone": "телефон",
"text": "номер",
"address": "адрес",
}
name: "имя",
email: "почта",
phone: "телефон",
text: "номер",
address: "адрес",
};
interface Props {
quiz: Quiz;
@ -59,6 +59,8 @@ interface Props {
setPageOfFields: () => void;
setSelectedCurrentFields: any;
handleCloseModal: any;
leadFlag: boolean;
leadFlagHC: (s: boolean) => void;
}
export const SwitchPages = ({
@ -89,16 +91,20 @@ export const SwitchPages = ({
setPageOfFields,
setSelectedCurrentFields,
handleCloseModal,
leadFlag,
leadFlagHC,
fullArrayOfPipelinesSteps,
}: Props) => {
const [step, setStep] = useState(0)
const [specialPage, setSpecialPage] = useState<"deleteCell" | "removeAccount" | "settingsBlock" | "accountInfo" | "amoLogin" | "">(accountInfo ? "accountInfo" : "amoLogin")
const [step, setStep] = useState(0);
const [specialPage, setSpecialPage] = useState<
"deleteCell" | "removeAccount" | "settingsBlock" | "accountInfo" | "bitrixLogin" | ""
>(accountInfo ? "accountInfo" : "bitrixLogin");
const [openDelete, setOpenDelete] = useState<TagQuestionHC | null>(null);
const startDeleteTagQuestion = (itemForDelete) => {
setOpenDelete(itemForDelete)
setSpecialPage("deleteCell")
}
setOpenDelete(itemForDelete);
setSpecialPage("deleteCell");
};
const minifiedQuestions = useMemo(
() =>
@ -110,47 +116,50 @@ export const SwitchPages = ({
})),
[questions]
);
const FieldsAllowedFC = useMemo(
() => {
const list: MinifiedData[] = []
if (quiz.config.showfc) {
const fields = quiz.config.formContact.fields
for (let key in fields) {
if (fields[key].used) list.push({
const FieldsAllowedFC = useMemo(() => {
const list: MinifiedData[] = [];
if (quiz.config.showfc) {
const fields = quiz.config.formContact.fields;
for (let key in fields) {
if (fields[key].used)
list.push({
id: key,
title: FCTranslate[key],
entity: "Contact",
})
}
});
}
return list;
},
[quiz]
);
}
return list;
}, [quiz]);
const handleAddTagQuestion = (scope: QuestionKeys | TagKeys, id: string, type: "question" | "tag") => {
if (!scope || !id) return;
if (type === "tag") {
setSelectedTags((prevState) => {
return({
...prevState,
[scope]: [...prevState[scope as TagKeys], id],
})});
return {
...prevState,
[scope]: [...prevState[scope as TagKeys], id],
};
});
}
if (type === "question") {
const q = questions.find(e => e.backendId === Number(id))
const q = questions.find((e) => e.backendId === Number(id));
setSelectedQuestions((prevState) => {
return ({
...prevState,
[scope]: [...prevState[scope as QuestionKeys], {
id,
title: q?.title || "вопрос",
entity: scope,
}],
})});
return {
...prevState,
[scope]: [
...prevState[scope as QuestionKeys],
{
id,
title: q?.title || "вопрос",
entity: scope,
},
],
};
});
}
}
};
const handleDeleteTagQuestion = () => {
if (openDelete === null || !openDelete.scope || !openDelete.id || !openDelete.type) return;
@ -166,15 +175,16 @@ export const SwitchPages = ({
}
if (openDelete.type === "question") {
let newArray = selectedQuestions
newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(e => e.id !== openDelete.id)
let newArray = selectedQuestions;
newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(
(e) => e.id !== openDelete.id
);
setSelectedQuestions(newArray);
setSelectedCurrentFields(selectedCurrentFields.filter(e => e.id !== openDelete.id));
setSelectedCurrentFields(selectedCurrentFields.filter((e) => e.id !== openDelete.id));
}
setOpenDelete(null);
closeSpecialPage();
}
};
const handleNextStep = () => {
setStep((prevState) => prevState + 1);
@ -190,20 +200,39 @@ export const SwitchPages = ({
const body = {
PipelineID: Number(selectedPipeline),
StepID: Number(selectedPipelineStep),
PerformerID: Number(selectedDealUser),
PerformerID: selectedDealUser,
LeadFlag: leadFlag,
StageID: "",
SourceID: "",
StatusID: "",
// FieldsRule: questionsBackend,
TagsToAdd: selectedTags,
// TagsToAdd: selectedTags,
};
const step = fullArrayOfPipelinesSteps.find((step) => step.bitrixID === selectedPipelineStep);
console.log("CURRENT step CURRENT step CURRENT step CURRENT step CURRENT step CURRENT step CURRENT step ");
console.log(step);
console.log(step.entityID);
console.log(step.entityID === "STATUS");
// if (step.entityId === undefined) return
if (step.entityID === "SOURCE") body.SourceID = step.statusID;
if (step.entityID === "STATUS") body.StatusID = step.statusID;
if (step.entityID.startsWith("DEAL_STAGE") && leadFlag) body.StageID = step.statusID;
const FieldsRule = {
Company: { QuestionID: {} },
Lead: { QuestionID: {} },
Customer: { QuestionID: {} },
Contact: {
lead: { QuestionID: {} },
deal: { QuestionID: {} },
company: { QuestionID: {} },
contact: {
QuestionID: {},
ContactRuleMap: {
}
ContactRuleMap: {},
},
// CRM_INVOICE: { QuestionID: {} },
// CRM_SMART_INVOICE: { QuestionID: {} },
// CRM_QUOTE: { QuestionID: {} },
// CRM_REQUISITE: { QuestionID: {} },
};
for (let key in FieldsRule) {
@ -213,13 +242,12 @@ export const SwitchPages = ({
}
selectedCurrentFields.forEach((data) => {
if (data.entity === "Contact") {
FieldsRule.Contact.ContactRuleMap[data.id] = Number(data.amoId)
if (data.entity === "contact") {
FieldsRule.contact.ContactRuleMap[data.id] = Number(data.bitrixId);
} else {
FieldsRule[data.entity].QuestionID[data.id] = Number(data.amoId) || 0
FieldsRule[data.entity].QuestionID[data.id] = Number(data.bitrixId) || 0;
}
})
});
for (let key in body.TagsToAdd) {
body.TagsToAdd[key as TagKeys] = body.TagsToAdd[key as TagKeys].map((id) => Number(id));
@ -235,17 +263,33 @@ export const SwitchPages = ({
handleCloseModal();
};
const closeSpecialPage = () => setSpecialPage("")
const closeSpecialPage = () => setSpecialPage("");
const steps = [
{
isSettingsAvailable: true,
component: (
<СhoosePerson
leadFlag={leadFlag}
leadFlagHC={leadFlagHC}
handlePrevStep={() => setSpecialPage("accountInfo")}
handleNextStep={handleNextStep}
titleProps={{
step: step + 2,
title: "Выбор этапа взаимодействия",
desc: "",
toSettings: () => setSpecialPage("settingsBlock"),
}}
/>
),
},
{
isSettingsAvailable: true,
component: (
<Pipelines
users={arrayOfUsers}
pipelines={arrayOfPipelines}
handlePrevStep={() => setSpecialPage("accountInfo")}
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
selectedDealUser={selectedDealUser}
setSelectedDealPerformer={setSelectedDealPerformer}
@ -255,7 +299,7 @@ export const SwitchPages = ({
step: step + 2,
title: "Выбор воронки",
desc: "На этом этапе вы можете выбрать нужную воронку и ответственного за сделку",
toSettings: () => setSpecialPage("settingsBlock")
toSettings: () => setSpecialPage("settingsBlock"),
}}
onScroll={setPageOfPipelines}
onScrollUsers={setPageOfUsers}
@ -278,10 +322,11 @@ export const SwitchPages = ({
step: step + 2,
title: "Выбор этапа воронки",
desc: "На этом этапе вы можете выбрать нужный этап и ответственного за сделку",
toSettings: () => setSpecialPage("settingsBlock")
toSettings: () => setSpecialPage("settingsBlock"),
}}
onScroll={setPageOfPipelinesSteps}
onScrollUsers={setPageOfUsers}
leadFlag={leadFlag}
/>
),
},
@ -298,36 +343,36 @@ export const SwitchPages = ({
step: step + 2,
title: "Сделка",
desc: "На этом этапе вы можете выбрать ответственного за сделку",
toSettings: () => setSpecialPage("settingsBlock")
toSettings: () => setSpecialPage("settingsBlock"),
}}
onScrollUsers={setPageOfUsers}
/>
),
},
// {
// isSettingsAvailable: true,
// component: (
// <BitrixTags
// tagsItems={arrayOfTags}
// selectedTags={selectedTags}
// openDelete={startDeleteTagQuestion}
// handleAddTag={handleAddTagQuestion}
// handlePrevStep={handlePrevStep}
// handleNextStep={handleNextStep}
// titleProps={{
// step: step + 2,
// title: "Добавление тегов",
// desc: "На этом этапе вы можете добавить теги с результатами",
// toSettings: () => setSpecialPage("settingsBlock")
// }}
// onScroll={setPageOfTags}
// />
// ),
// },
{
isSettingsAvailable: true,
component: (
<AmoTags
tagsItems={arrayOfTags}
selectedTags={selectedTags}
openDelete={startDeleteTagQuestion}
handleAddTag={handleAddTagQuestion}
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
titleProps={{
step: step + 2,
title: "Добавление тегов",
desc: "На этом этапе вы можете добавить теги с результатами",
toSettings: () => setSpecialPage("settingsBlock")
}}
onScroll={setPageOfTags}
/>
),
},
{
isSettingsAvailable: true,
component: (
<AmoQuestions
<BitrixQuestions
setSelectedCurrentFields={setSelectedCurrentFields}
fieldsItems={arrayOfFields}
selectedCurrentFields={selectedCurrentFields}
@ -341,56 +386,71 @@ export const SwitchPages = ({
titleProps={{
step: step + 2,
title: "Соотнесение вопросов и сущностей",
toSettings: () => setSpecialPage("settingsBlock")
toSettings: () => setSpecialPage("settingsBlock"),
}}
onScroll={setPageOfFields}
/>
),
},
]
];
const stepTitles = steps.map((step) => step.title);
switch (specialPage) {
case "deleteCell":
return <DeleteTagQuestion
close={closeSpecialPage}
deleteItem={handleDeleteTagQuestion}
/>
return (
<DeleteTagQuestion
close={closeSpecialPage}
deleteItem={handleDeleteTagQuestion}
/>
);
case "removeAccount":
return <RemoveAccount
handleCloseModal={handleCloseModal}
stopThisPage={closeSpecialPage}
/>
return (
<RemoveAccount
handleCloseModal={handleCloseModal}
stopThisPage={closeSpecialPage}
/>
);
case "settingsBlock":
return <SettingsBlock
stepTitles={stepTitles}
selectedDealUser={arrayOfUsers.find((u) => u.id === selectedDealUser)?.title || "не указан"}
selectedFunnel={arrayOfPipelines.find((p) => p.id === selectedPipeline)?.title || "нет данных"}
selectedStage={
arrayOfPipelinesSteps.find((s) => s.id === selectedPipelineStep)?.title || "нет данных"
}
selectedQuestions={selectedQuestions}
selectedTags={selectedTags}
toBack={() => closeSpecialPage()}
setStep={(step: number) => {
closeSpecialPage()
setStep(step - 1)
}}
/>
case "amoLogin": return <AmoLogin handleNextStep={handleNextStep} />
case "accountInfo": return <AccountInfo
handleNextStep={() => closeSpecialPage()}
accountInfo={accountInfo}
toChangeAccount={() => setSpecialPage("removeAccount")}
/>
return (
<SettingsBlock
stepTitles={stepTitles}
selectedDealUser={arrayOfUsers.find((u) => u.id === selectedDealUser)?.title || "не указан"}
selectedFunnel={arrayOfPipelines.find((p) => p.id === selectedPipeline)?.title || "нет данных"}
selectedStage={arrayOfPipelinesSteps.find((s) => s.id === selectedPipelineStep)?.title || "нет данных"}
selectedQuestions={selectedQuestions}
selectedTags={selectedTags}
toBack={() => closeSpecialPage()}
setStep={(step: number) => {
closeSpecialPage();
setStep(step - 1);
}}
leadFlag={leadFlag}
/>
);
case "bitrixLogin":
return <BitrixLogin handleNextStep={handleNextStep} />;
case "accountInfo":
return (
<AccountInfo
handleNextStep={() => closeSpecialPage()}
accountInfo={accountInfo}
toChangeAccount={() => setSpecialPage("removeAccount")}
/>
);
default: return <Box sx={{
flexGrow: 1,
width: "100%",
height: "100%",
overflow: "auto"
}}>{steps[step].component}</Box>
default:
return (
<Box
sx={{
flexGrow: 1,
width: "100%",
height: "100%",
overflow: "auto",
}}
>
{steps[step].component}
</Box>
);
}
}
};

@ -6,7 +6,7 @@ import { MinifiedData, QuestionKeys, SelectedTags, TagKeys, TagQuestionHC } from
import { DataConstrictor } from "../Components/DataConstrictor";
import { ModalTitle } from "../ModalTitle";
import { StepButtonsBlock } from "../StepButtonsBlock";
import { resetBitrixTagsFields } from "../useAmoIntegration";
import { resetBitrixTagsFields } from "../useBitrixIntegration";
type Props = {
tagsItems: MinifiedData[] | [];
@ -25,7 +25,7 @@ type Props = {
};
export const AmoTags: FC<Props> = ({
export const BitrixTags: FC<Props> = ({
tagsItems,
selectedTags,
handleAddTag,

@ -5,7 +5,7 @@ import { redirect } from "react-router-dom";
import CloseIcon from "@mui/icons-material/Close";
import { useBitrixIntegration } from "./useAmoIntegration";
import { useBitrixIntegration } from "./useBitrixIntegration";
import { MinifiedData } from "./types";
import { Quiz } from "@/model/quiz/quiz";
import { SwitchPages } from "./SwitchPages";
@ -60,11 +60,14 @@ export const BitrixModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
setPageOfTags,
setPageOfFields,
setSelectedCurrentFields,
leadFlag,
leadFlagHC,
fullArrayOfPipelinesSteps
} = useBitrixIntegration({
quizID: quiz.backendId,
isModalOpen,
isTryRemoveAccount,
questions,
questions
});
return (
@ -160,6 +163,9 @@ export const BitrixModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
setPageOfFields={setPageOfFields}
setSelectedCurrentFields={setSelectedCurrentFields}
handleCloseModal={handleCloseModal}
leadFlag={leadFlag}
leadFlagHC={leadFlagHC}
fullArrayOfPipelinesSteps={fullArrayOfPipelinesSteps}
/>
}
</Box>

@ -1,7 +1,22 @@
export type TagKeys = "Company" | "Lead" | "Customer" | "Contact";
export type TagKeys = "lead"
| "company"
| "contact"
| "deal"
| "CRM_INVOICE"
| "CRM_SMART_INVOICE"
| "CRM_QUOTE"
| "CRM_REQUISITE";
export type SelectedTags = Record<TagKeys, number[]>;
export type QuestionKeys = "Company" | "Lead" | "Customer" | "Contact";
export type QuestionKeys = "lead"
| "company"
| "contact"
| "deal"
| "CRM_INVOICE"
| "CRM_SMART_INVOICE"
| "CRM_QUOTE"
| "CRM_REQUISITE";
export type SelectedQuestions = Record<QuestionKeys, MinifiedData[]>;
export type MinifiedData = {

@ -11,6 +11,7 @@ import {
getAccount,
FieldsRule,
getFields,
connectBitrix,
} from "@/api/bitrixIntegration";
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import { UntypedQuizQuestion } from "@/model/questionTypes/shared";
@ -43,8 +44,11 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
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[]>([]);
@ -62,10 +66,14 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
Customer: [],
});
const [selectedQuestions, setSelectedQuestions] = useState<SelectedQuestions>({
Lead: [],
Company: [],
Customer: [],
Contact: []
lead: [],
company: [],
contact: [],
deal: [],
CRM_INVOICE: [],
CRM_SMART_INVOICE: [],
CRM_QUOTE: [],
CRM_REQUISITE: [],
});
const [pageOfPipelines, setPageOfPipelines] = useState(1);
@ -74,12 +82,37 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
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);
@ -138,7 +171,7 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
id: key,
title: FCTranslate[key],
entity: "Contact",
amoId: MAP[key].toString(),
bitrixId: MAP[key].toString(),
})
}
setSelectedCurrentFields(list)
@ -196,8 +229,8 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
response.items.forEach((step) => {
minifiedPipelines.push({
id: step.AmoID.toString(),
title: step.Name,
id: step.bitrixID.toString(),
title: step.name || "Нет названия",
});
});
setArrayOfPipelines((prevItems) => [...prevItems, ...minifiedPipelines]);
@ -208,31 +241,44 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
});
}
}, [pageOfPipelines]);
useEffect(() => {
if (isReadyGetPipelineStep) {
const oldData = pageOfPipelinesSteps === 1 ? [] : arrayOfPipelinesSteps;
if (selectedPipeline !== null)
getSteps({
page: pageOfPipelinesSteps,
size: SIZE,
pipelineId: Number(selectedPipeline),
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedSteps: MinifiedData[] = [];
useEffect(() => {
if (isReadyGetPipelineStep && selectedPipeline !== null) {
const oldData = pageOfPipelinesSteps === 1 ? [] : arrayOfPipelinesSteps;
const oldFullData = pageOfPipelinesSteps === 1 ? [] : fullArrayOfPipelinesSteps;
response.items.forEach((step) => {
minifiedSteps.push({
id: step.AmoID.toString(),
title: step.Name,
});
});
setArrayOfPipelinesSteps([...oldData, ...minifiedSteps]);
} else {
isReadyGetPipelineStep = false
}
});
}
}, [selectedPipeline, pageOfPipelinesSteps]);
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({
@ -244,8 +290,8 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
response.items.forEach((step) => {
minifiedUsers.push({
id: step.amoUserID.toString(),
title: step.name,
id: step.bitrixUserID.toString(),
title: step.name || "Нет имени",
});
});
setArrayOfUsers((prevItems) => [...prevItems, ...minifiedUsers]);
@ -255,66 +301,77 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
});
}
}, [pageOfUsers]);
useEffect(() => {
if (isReadyGetTags) {
getTags({
page: pageOfTags,
size: SIZE,
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedTags: MinifiedData[] = [];
// 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.AmoID.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]);
// 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[] = [];
if (isReadyGetFields) {
getFields({
page: pageOfFields,
size: 1000,
}).then(([response]) => {
if (response && response.items !== null) {
const minifiedTags: MinifiedData[] = [];
response.items.forEach((field) => {
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.AmoID.toString(),
title: field.Name,
entity:
field.Entity === "leads"
? "Lead"
: field.Entity === "contacts"
? "Contact"
: field.Entity === "companies"
? "Company"
: "Customer",
id: field.bitrixID.toString(),
title: field.editFromLabel,
entity: entity,
});
});
setArrayOfFields((prevItems) => [...prevItems, ...minifiedTags]);
}
});
} else {
isReadyGetFields = false
}
}, [pageOfFields]);
}
});
setArrayOfFields((prevItems) => [...prevItems, ...minifiedTags]);
}
});
} else {
isReadyGetFields = false
}
}, [pageOfFields]);
useEffect(() => () => {
isReadyGetPipeline = true;
isReadyGetPipelineStep = true;
@ -350,6 +407,9 @@ export const useBitrixIntegration = ({ isModalOpen, isTryRemoveAccount, quizID,
setPageOfTags: () => setPageOfTags(old => old + 1),
setPageOfFields: () => setPageOfFields(old => old + 1),
setSelectedCurrentFields,
leadFlag,
leadFlagHC,
fullArrayOfPipelinesSteps
};
};

@ -0,0 +1,136 @@
import { Box, FormControl, FormControlLabel, Radio, RadioGroup, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "./StepButtonsBlock";
import CheckboxIcon from "@/assets/icons/Checkbox";
import { ModalTitle } from "./ModalTitle";
type Props = {
leadFlag: boolean;
leadFlagHC: (a: boolean) => void;
handlePrevStep: () => void;
handleNextStep: () => void;
titleProps: {
step: number;
title: string;
desc: string;
toSettings: () => void;
};
};
export const СhoosePerson: FC<Props> = ({
leadFlag,
leadFlagHC,
handlePrevStep,
handleNextStep,
titleProps,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
return (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
overflow: "auto",
flexGrow: 1,
justifyContent: "space-between",
}}
>
<Box sx={{ width: "100%", zIndex: 3 }}>
<ModalTitle {...titleProps} />
</Box>
<Box>
<FormControl component="fieldset">
<RadioGroup
row
aria-label="тип сделки"
name="dealType"
value={leadFlag ? "lead" : "deal"}
onChange={(e) => leadFlagHC(e.target.value === "lead")}
sx={{ gap: 3 }}
>
<FormControlLabel
value="lead"
control={
<Radio
checkedIcon={
<CheckboxIcon
checked
isRounded
color={theme.palette.brightPurple.main}
/>
}
icon={<CheckboxIcon isRounded />}
/>
}
label="Лид сделки"
sx={{
color: "black",
padding: "15px",
border: `1px solid ${theme.palette.background.default}`,
borderRadius: "12px",
margin: 0,
backgroundColor: "#eff0f5",
"&.MuiFormControlLabel-root > .MuiTypography-root": {
width: isMobile ? "150px" : "200px",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
},
}}
/>
<FormControlLabel
value="deal"
control={
<Radio
checkedIcon={
<CheckboxIcon
checked
isRounded
color={theme.palette.brightPurple.main}
/>
}
icon={<CheckboxIcon isRounded />}
/>
}
label="Дил сделки"
sx={{
color: "black",
padding: "15px",
border: `1px solid ${theme.palette.background.default}`,
borderRadius: "12px",
margin: 0,
backgroundColor: "#eff0f5",
"&.MuiFormControlLabel-root > .MuiTypography-root": {
width: isMobile ? "150px" : "200px",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
},
}}
/>
</RadioGroup>
</FormControl>
</Box>
<Box
sx={{
alignSelf: "end",
}}
>
<StepButtonsBlock
onLargeBtnClick={handleNextStep}
onSmallBtnClick={handlePrevStep}
/>
</Box>
</Box>
</>
);
};

@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
import { PartnersBoard } from "./PartnersBoard/PartnersBoard";
import { getLeadTargetsByQuiz, LeadTargetModel } from "@/api/leadtarget";
import { QuizMetricType } from "@model/quizSettings";
import { makeRequest } from "@frontend/kitui";
interface IntegrationsPageProps {
heightSidebar: number;
@ -56,6 +57,24 @@ export const IntegrationsPage = ({
load();
}, [leadTargetsLoaded, quiz?.id]);
// useEffect(() => {
// (async () => {
// const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/yclients`;
// try {
// const response = await makeRequest<void, { link: string }>({
// method: "POST",
// url: `${API_URL}/account`,
// useToken: true,
// withCredentials: true,
// });
// window.open(response.link, "_blank");
// } catch (nativeError) {
// return [null, `Не удалось подключить аккаунт. `];
// }
// })()
// }, [])
const refreshLeadTargets = async () => {
if (!quiz?.id) return;
const [items] = await getLeadTargetsByQuiz(quiz.backendId);

@ -140,7 +140,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
/>
</Box>
<Typography variant="h6" sx={sectionTitleStyles}>
<Typography variant="h6" sx={sectionTitleStyles}>
Автоматизация
</Typography>
<Box sx={containerStyles}>
@ -152,7 +152,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
setIsModalOpen={setIsPostbackModalOpen}
setCompanyName={setCompanyName}
/>
</Box>
</Box>
</Box>
{companyName && (