перевод имён вопросов в амо модалке
This commit is contained in:
parent
d717322f87
commit
4fa98f644f
@ -1,5 +1,5 @@
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "./StepButtonsBlock";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { AccountResponse } from "@api/integration";
|
import { AccountResponse } from "@api/integration";
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ type AmoAccountInfoProps = {
|
|||||||
accountInfo: AccountResponse;
|
accountInfo: AccountResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AmoAccountInfo: FC<AmoAccountInfoProps> = ({ handleNextStep, accountInfo }) => {
|
export const AccountInfo: FC<AmoAccountInfoProps> = ({ handleNextStep, accountInfo }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||||
|
|
||||||
@ -1,464 +0,0 @@
|
|||||||
import React, { FC, useCallback, useEffect, 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";
|
|
||||||
import { enqueueSnackbar } from "notistack";
|
|
||||||
|
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
|
||||||
|
|
||||||
import { AmoRemoveAccount } from "./AmoRemoveAccount/AmoRemoveAccount";
|
|
||||||
import { AmoDeleteTagQuestion } from "./AmoRemoveAccount/AmoDeleteTagQuestion";
|
|
||||||
import { AmoLogin } from "./AmoLogin/AmoLogin";
|
|
||||||
import { Pipelines } from "./Pipelines/Pipelines";
|
|
||||||
import { PipelineSteps } from "./PipelineSteps/PipelineSteps";
|
|
||||||
import { DealPerformers } from "./DealPerformers/DealPerformers";
|
|
||||||
import { AmoTags } from "./AmoTags/AmoTags";
|
|
||||||
import { AmoQuestions } from "./AmoQuestions/AmoQuestions";
|
|
||||||
import { AmoModalTitle } from "./AmoModalTitle/AmoModalTitle";
|
|
||||||
import { AmoSettingsBlock } from "./SettingsBlock/AmoSettingsBlock";
|
|
||||||
import { AmoAccountInfo } from "./AmoAccountInfo/AmoAccountInfo";
|
|
||||||
import { useAmoIntegration } from "./useAmoIntegration";
|
|
||||||
import { MinifiedData, QuestionKeys, TagKeys, TagQuestionHC } from "./types";
|
|
||||||
import { Quiz } from "@/model/quiz/quiz";
|
|
||||||
import { setIntegrationRules, updateIntegrationRules } from "@/api/integration";
|
|
||||||
|
|
||||||
type IntegrationsModalProps = {
|
|
||||||
isModalOpen: boolean;
|
|
||||||
handleCloseModal: () => void;
|
|
||||||
companyName: string | null;
|
|
||||||
quiz: Quiz;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FCTranslate = {
|
|
||||||
"name": "имя",
|
|
||||||
"email": "почта",
|
|
||||||
"phone": "телефон",
|
|
||||||
"text": "номер",
|
|
||||||
"address": "адрес",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleCloseModal, companyName, quiz }) => {
|
|
||||||
//Если нет контекста квиза, то и делать на этой страничке нечего
|
|
||||||
if (quiz?.backendId === undefined) {
|
|
||||||
redirect("/list");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
|
||||||
|
|
||||||
const { questions } = useQuestions();
|
|
||||||
const minifiedQuestions = useMemo(
|
|
||||||
() =>
|
|
||||||
questions
|
|
||||||
.filter((q) => q.type !== "result" && q.type !== null)
|
|
||||||
.map(({ backendId, title }) => ({
|
|
||||||
id: backendId.toString() as string,
|
|
||||||
title,
|
|
||||||
})),
|
|
||||||
[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({
|
|
||||||
id: key,
|
|
||||||
title: FCTranslate[key],
|
|
||||||
entity: "Contact",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
},
|
|
||||||
[quiz]
|
|
||||||
);
|
|
||||||
|
|
||||||
const [step, setStep] = useState<number>(0);
|
|
||||||
const [isSettingsBlock, setIsSettingsBlock] = useState<boolean>(false);
|
|
||||||
const [isTryRemoveAccount, setIsTryRemoveAccount] = useState<boolean>(false);
|
|
||||||
const [openDelete, setOpenDelete] = useState<TagQuestionHC | null>(null);
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
isLoadingPage,
|
|
||||||
firstRules,
|
|
||||||
accountInfo,
|
|
||||||
arrayOfPipelines,
|
|
||||||
arrayOfPipelinesSteps,
|
|
||||||
arrayOfUsers,
|
|
||||||
arrayOfTags,
|
|
||||||
arrayOfFields,
|
|
||||||
selectedPipeline,
|
|
||||||
setSelectedPipeline,
|
|
||||||
selectedCurrentFields,
|
|
||||||
selectedPipelineStep,
|
|
||||||
setSelectedPipelineStep,
|
|
||||||
selectedDealUser,
|
|
||||||
setSelectedDealPerformer,
|
|
||||||
questionsBackend,
|
|
||||||
selectedTags,
|
|
||||||
setSelectedTags,
|
|
||||||
selectedQuestions,
|
|
||||||
setSelectedQuestions,
|
|
||||||
setPageOfPipelines,
|
|
||||||
setPageOfPipelinesSteps,
|
|
||||||
setPageOfUsers,
|
|
||||||
setPageOfTags,
|
|
||||||
setSelectedCurrentFields,
|
|
||||||
} = useAmoIntegration({
|
|
||||||
quizID: quiz.backendId,
|
|
||||||
isModalOpen,
|
|
||||||
isTryRemoveAccount,
|
|
||||||
questions,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const handleAddTagQuestion = useCallback(
|
|
||||||
(scope: QuestionKeys | TagKeys, id: string, type: "question" | "tag") => {
|
|
||||||
if (!scope || !id) return;
|
|
||||||
|
|
||||||
if (type === "tag") {
|
|
||||||
setSelectedTags((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[scope]: [...prevState[scope as TagKeys], id],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === "question") {
|
|
||||||
const q = questions.find(e => e.backendId === Number(id))
|
|
||||||
setSelectedQuestions((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[scope]: [...prevState[scope as QuestionKeys], {
|
|
||||||
id,
|
|
||||||
title: q?.title || "вопрос",
|
|
||||||
entity: scope,
|
|
||||||
}],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setSelectedQuestions, setSelectedTags, questions]
|
|
||||||
);
|
|
||||||
const handleDeleteTagQuestion = useCallback(() => {
|
|
||||||
if (openDelete === null || !openDelete.scope || !openDelete.id || !openDelete.type) return;
|
|
||||||
if (openDelete.type === "tag") {
|
|
||||||
let newArray = selectedTags[openDelete.scope];
|
|
||||||
const index = newArray.indexOf(openDelete.id);
|
|
||||||
if (index !== -1) newArray.splice(index, 1);
|
|
||||||
|
|
||||||
setSelectedTags((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[openDelete.scope]: newArray,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openDelete.type === "question") {
|
|
||||||
let newArray = selectedQuestions
|
|
||||||
newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(e => e.id !== openDelete.id)
|
|
||||||
// let index = -1
|
|
||||||
// selectedQuestions[openDelete.scope].forEach((e, i) => {
|
|
||||||
// if (e.subTitle === openDelete.id) index = i
|
|
||||||
// })
|
|
||||||
// if (index !== -1) newArray.splice(index, 1);
|
|
||||||
// setSelectedQuestions((prevState) => ({
|
|
||||||
// ...prevState,
|
|
||||||
// [openDelete.scope]: newArray,
|
|
||||||
// }));
|
|
||||||
setSelectedQuestions(newArray);
|
|
||||||
setSelectedCurrentFields(selectedCurrentFields.filter(e => e.id !== openDelete.id));
|
|
||||||
|
|
||||||
}
|
|
||||||
setOpenDelete(null);
|
|
||||||
}, [openDelete]);
|
|
||||||
|
|
||||||
const handleNextStep = () => {
|
|
||||||
setStep((prevState) => prevState + 1);
|
|
||||||
};
|
|
||||||
const handlePrevStep = () => {
|
|
||||||
setStep((prevState) => prevState - 1);
|
|
||||||
};
|
|
||||||
const handleSave = () => {
|
|
||||||
if (quiz?.backendId === undefined) return;
|
|
||||||
if (selectedPipeline === null) return enqueueSnackbar("Выберите воронку");
|
|
||||||
if (selectedPipeline === null) return enqueueSnackbar("Выберите этап воронки");
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
PipelineID: Number(selectedPipeline),
|
|
||||||
StepID: Number(selectedPipelineStep),
|
|
||||||
PerformerID: Number(selectedDealUser),
|
|
||||||
// FieldsRule: questionsBackend,
|
|
||||||
TagsToAdd: selectedTags,
|
|
||||||
};
|
|
||||||
|
|
||||||
const FieldsRule = {
|
|
||||||
Company: { QuestionID: {} },
|
|
||||||
Lead: { QuestionID: {} },
|
|
||||||
Customer: { QuestionID: {} },
|
|
||||||
Contact: {
|
|
||||||
QuestionID: {},
|
|
||||||
ContactRuleMap: {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let key in FieldsRule) {
|
|
||||||
selectedQuestions[key as QuestionKeys].forEach((data) => {
|
|
||||||
FieldsRule[key as QuestionKeys].QuestionID[data.id] = 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedCurrentFields.forEach((data) => {
|
|
||||||
if (data.entity === "Contact") {
|
|
||||||
FieldsRule.Contact.ContactRuleMap[data.id] = Number(data.amoId)
|
|
||||||
} else {
|
|
||||||
FieldsRule[data.entity].QuestionID[data.id] = Number(data.amoId) || 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
for (let key in body.TagsToAdd) {
|
|
||||||
body.TagsToAdd[key as TagKeys] = body.TagsToAdd[key as TagKeys].map((id) => Number(id));
|
|
||||||
}
|
|
||||||
body.FieldsRule = FieldsRule;
|
|
||||||
|
|
||||||
if (firstRules) {
|
|
||||||
setIntegrationRules(quiz.backendId.toString(), body);
|
|
||||||
} else {
|
|
||||||
updateIntegrationRules(quiz.backendId.toString(), body);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCloseModal();
|
|
||||||
setStep(1);
|
|
||||||
};
|
|
||||||
const steps = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
title: accountInfo ? "Информация об аккаунте" : "Авторизация в аккаунте",
|
|
||||||
isSettingsAvailable: false,
|
|
||||||
component: accountInfo ? (
|
|
||||||
<AmoAccountInfo
|
|
||||||
handleNextStep={handleNextStep}
|
|
||||||
accountInfo={accountInfo}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AmoLogin handleNextStep={handleNextStep} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Выбор воронки",
|
|
||||||
desc: "На этом этапе вы можете выбрать нужную воронку и ответственного за сделку",
|
|
||||||
isSettingsAvailable: true,
|
|
||||||
component: (
|
|
||||||
<Pipelines
|
|
||||||
users={arrayOfUsers}
|
|
||||||
pipelines={arrayOfPipelines}
|
|
||||||
handlePrevStep={handlePrevStep}
|
|
||||||
handleNextStep={handleNextStep}
|
|
||||||
selectedDealUser={selectedDealUser}
|
|
||||||
setSelectedDealPerformer={setSelectedDealPerformer}
|
|
||||||
selectedPipeline={selectedPipeline}
|
|
||||||
setSelectedPipeline={setSelectedPipeline}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Выбор этапа воронки",
|
|
||||||
desc: "На этом этапе вы можете выбрать нужный этап и ответственного за сделку",
|
|
||||||
isSettingsAvailable: true,
|
|
||||||
component: (
|
|
||||||
<PipelineSteps
|
|
||||||
users={arrayOfUsers}
|
|
||||||
selectedDealUser={selectedDealUser}
|
|
||||||
selectedStep={selectedPipelineStep}
|
|
||||||
steps={arrayOfPipelinesSteps}
|
|
||||||
setSelectedDealPerformer={setSelectedDealPerformer}
|
|
||||||
setSelectedStep={setSelectedPipelineStep}
|
|
||||||
handlePrevStep={handlePrevStep}
|
|
||||||
handleNextStep={handleNextStep}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Сделка",
|
|
||||||
desc: "На этом этапе вы можете выбрать ответственного за сделку",
|
|
||||||
isSettingsAvailable: true,
|
|
||||||
component: (
|
|
||||||
<DealPerformers
|
|
||||||
handlePrevStep={handlePrevStep}
|
|
||||||
handleNextStep={handleNextStep}
|
|
||||||
users={arrayOfUsers}
|
|
||||||
selectedDealUser={selectedDealUser}
|
|
||||||
setSelectedDealPerformer={setSelectedDealPerformer}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Добавление тегов",
|
|
||||||
isSettingsAvailable: true,
|
|
||||||
component: (
|
|
||||||
<AmoTags
|
|
||||||
tagsItems={arrayOfTags}
|
|
||||||
selectedTags={selectedTags}
|
|
||||||
openDelete={setOpenDelete}
|
|
||||||
handleScroll={() => { }}
|
|
||||||
handleAddTag={handleAddTagQuestion}
|
|
||||||
handlePrevStep={handlePrevStep}
|
|
||||||
handleNextStep={handleNextStep}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Соотнесение вопросов и сущностей",
|
|
||||||
isSettingsAvailable: true,
|
|
||||||
component: (
|
|
||||||
<AmoQuestions
|
|
||||||
setSelectedCurrentFields={setSelectedCurrentFields}
|
|
||||||
fieldsItems={arrayOfFields}
|
|
||||||
selectedCurrentFields={selectedCurrentFields}
|
|
||||||
questionsItems={minifiedQuestions}
|
|
||||||
selectedQuestions={selectedQuestions}
|
|
||||||
openDelete={setOpenDelete}
|
|
||||||
handleAddQuestion={handleAddTagQuestion}
|
|
||||||
handlePrevStep={handlePrevStep}
|
|
||||||
handleNextStep={handleSave}
|
|
||||||
FieldsAllowedFC={FieldsAllowedFC}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
arrayOfPipelines,
|
|
||||||
arrayOfPipelinesSteps,
|
|
||||||
arrayOfUsers,
|
|
||||||
arrayOfTags,
|
|
||||||
arrayOfFields,
|
|
||||||
selectedPipeline,
|
|
||||||
selectedPipelineStep,
|
|
||||||
selectedDealUser,
|
|
||||||
selectedQuestions,
|
|
||||||
selectedTags,
|
|
||||||
arrayOfPipelines,
|
|
||||||
arrayOfPipelinesSteps,
|
|
||||||
arrayOfUsers,
|
|
||||||
minifiedQuestions,
|
|
||||||
selectedCurrentFields,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const stepTitles = steps.map((step) => step.title);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog
|
|
||||||
open={isModalOpen}
|
|
||||||
onClose={handleCloseModal}
|
|
||||||
fullWidth
|
|
||||||
// fullScreen={isMobile}
|
|
||||||
PaperProps={{
|
|
||||||
sx: {
|
|
||||||
maxWidth: isTablet ? "100%" : "920px",
|
|
||||||
maxHeight: isTablet ? "100%" : "680px",
|
|
||||||
borderRadius: "12px",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
height: "68px",
|
|
||||||
backgroundColor: theme.palette.background.default,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: isMobile ? "20px" : "24px",
|
|
||||||
fontWeight: "500",
|
|
||||||
padding: "20px",
|
|
||||||
color: theme.palette.grey2.main,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Интеграция с {companyName ? companyName : "партнером"}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<IconButton
|
|
||||||
onClick={handleCloseModal}
|
|
||||||
sx={{
|
|
||||||
width: "12px",
|
|
||||||
height: "12px",
|
|
||||||
position: "absolute",
|
|
||||||
right: "15px",
|
|
||||||
top: "15px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CloseIcon sx={{ width: "12px", height: "12px", transform: "scale(1.5)" }} />
|
|
||||||
</IconButton>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: isTablet ? "100%" : "920px",
|
|
||||||
height: "600px",
|
|
||||||
padding: "15px 20px 15px",
|
|
||||||
flexGrow: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isLoadingPage ?
|
|
||||||
<Skeleton
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
transform: "none",
|
|
||||||
}}
|
|
||||||
/> :
|
|
||||||
<>
|
|
||||||
<AmoModalTitle
|
|
||||||
step={step}
|
|
||||||
steps={steps}
|
|
||||||
isSettingsBlock={isSettingsBlock}
|
|
||||||
setIsSettingsBlock={setIsSettingsBlock}
|
|
||||||
setStep={setStep}
|
|
||||||
startRemoveAccount={() => setIsTryRemoveAccount(true)}
|
|
||||||
/>
|
|
||||||
{openDelete !== null ? (
|
|
||||||
<AmoDeleteTagQuestion
|
|
||||||
close={() => setOpenDelete(null)}
|
|
||||||
deleteItem={handleDeleteTagQuestion}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{isTryRemoveAccount && <AmoRemoveAccount handleCloseModal={handleCloseModal} stopThisPage={() => setIsTryRemoveAccount(false)} />}
|
|
||||||
{isSettingsBlock && (
|
|
||||||
<Box sx={{ flexGrow: 1, width: "100%" }}>
|
|
||||||
<AmoSettingsBlock
|
|
||||||
stepTitles={stepTitles}
|
|
||||||
setIsSettingsBlock={setIsSettingsBlock}
|
|
||||||
setStep={setStep}
|
|
||||||
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}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
{!isSettingsBlock && !isTryRemoveAccount && (
|
|
||||||
<Box sx={{ flexGrow: 1, width: "100%" }}>{steps[step].component}</Box>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const diffArr = (arr_A: MinifiedData[], arr_B: MinifiedData[]) => {
|
|
||||||
return arr_A.filter(person_A => !arr_B.some(person_B => person_A.id === person_B.id));
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { AmoButton } from "../../../../../components/AmoButton/AmoButton";
|
import { AmoButton } from "../../../../components/AmoButton/AmoButton";
|
||||||
import { connectAmo } from "@api/integration";
|
import { connectAmo } from "@api/integration";
|
||||||
|
|
||||||
type IntegrationStep1Props = {
|
type IntegrationStep1Props = {
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "./StepButtonsBlock";
|
||||||
import { CustomSelect } from "../../../../../components/CustomSelect/CustomSelect";
|
import { CustomSelect } from "../../../../components/CustomSelect/CustomSelect";
|
||||||
import { MinifiedData } from "../types";
|
import { MinifiedData } from "./types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
users: MinifiedData[];
|
users: MinifiedData[];
|
||||||
@ -6,7 +6,7 @@ interface Props {
|
|||||||
close: () => void;
|
close: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AmoDeleteTagQuestion: FC<Props> = ({ close, deleteItem }) => {
|
export const DeleteTagQuestion: FC<Props> = ({ close, deleteItem }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -13,7 +13,7 @@ type AmoModalTitleProps = {
|
|||||||
startRemoveAccount: () => void;
|
startRemoveAccount: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AmoModalTitle: FC<AmoModalTitleProps> = ({
|
export const ModalTitle: FC<AmoModalTitleProps> = ({
|
||||||
step,
|
step,
|
||||||
steps,
|
steps,
|
||||||
setIsSettingsBlock,
|
setIsSettingsBlock,
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "./StepButtonsBlock";
|
||||||
import { CustomSelect } from "../../../../../components/CustomSelect/CustomSelect";
|
import { CustomSelect } from "../../../../components/CustomSelect/CustomSelect";
|
||||||
import { CustomRadioGroup } from "../../../../../components/CustomRadioGroup/CustomRadioGroup";
|
import { CustomRadioGroup } from "../../../../components/CustomRadioGroup/CustomRadioGroup";
|
||||||
import { MinifiedData } from "../types";
|
import { MinifiedData } from "./types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
users: MinifiedData[];
|
users: MinifiedData[];
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "./StepButtonsBlock";
|
||||||
import { CustomSelect } from "../../../../../components/CustomSelect/CustomSelect";
|
import { CustomSelect } from "../../../../components/CustomSelect/CustomSelect";
|
||||||
import { CustomRadioGroup } from "../../../../../components/CustomRadioGroup/CustomRadioGroup";
|
import { CustomRadioGroup } from "../../../../components/CustomRadioGroup/CustomRadioGroup";
|
||||||
import { MinifiedData } from "../types";
|
import { MinifiedData } from "./types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
pipelines: MinifiedData[];
|
pipelines: MinifiedData[];
|
||||||
@ -4,7 +4,7 @@ import { ItemDetailsView } from "./ItemDetailsView/ItemDetailsView";
|
|||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { MinifiedData, QuestionKeys, SelectedQuestions, TagKeys, TagQuestionHC } from "../types";
|
import { MinifiedData, QuestionKeys, SelectedQuestions, TagKeys, TagQuestionHC } from "../types";
|
||||||
import { EntitiesQuestions } from "./EntitiesQuestions";
|
import { EntitiesQuestions } from "./EntitiesQuestions";
|
||||||
import { diffArr } from "../AmoCRMModal";
|
import { diffArr } from "..";
|
||||||
import { DataConstrictor } from "../Components/DataConstrictor";
|
import { DataConstrictor } from "../Components/DataConstrictor";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -2,7 +2,7 @@ import { CustomRadioGroup } from "@/components/CustomRadioGroup/CustomRadioGroup
|
|||||||
import {Box, Typography, useMediaQuery, useTheme} from "@mui/material"
|
import {Box, Typography, useMediaQuery, useTheme} from "@mui/material"
|
||||||
import { MinifiedData } from "../types";
|
import { MinifiedData } from "../types";
|
||||||
import {CustomSelect} from "@/components/CustomSelect/CustomSelect";
|
import {CustomSelect} from "@/components/CustomSelect/CustomSelect";
|
||||||
import {CurrentFieldSelect} from "@/pages/IntegrationsPage/IntegrationsModal/Amo/AmoQuestions/CurrentFieldSelectMobile";
|
import {CurrentFieldSelect} from "@/pages/IntegrationsPage/IntegrationsModal/Amo/Questions/CurrentFieldSelectMobile";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
items: MinifiedData[];
|
items: MinifiedData[];
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import {Box, Button, useMediaQuery, useTheme} from "@mui/material"
|
import {Box, Button, useMediaQuery, useTheme} from "@mui/material"
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock"
|
import { StepButtonsBlock } from "../StepButtonsBlock"
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { MinifiedData, TagKeys } from "../types";
|
import { MinifiedData, TagKeys } from "../types";
|
||||||
import { CurrentFields } from "./CurrentFields";
|
import { CurrentFields } from "./CurrentFields";
|
||||||
import { NewFields } from "./NewFields";
|
import { NewFields } from "./NewFields";
|
||||||
import { QuestionPair } from "./AmoQuestions";
|
import { QuestionPair } from "./AmoQuestions";
|
||||||
import { diffArr } from "../AmoCRMModal";
|
import { diffArr } from "..";
|
||||||
|
|
||||||
type ItemsSelectionViewProps = {
|
type ItemsSelectionViewProps = {
|
||||||
items: MinifiedData[] | [];
|
items: MinifiedData[] | [];
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { Box, useTheme } from "@mui/material";
|
import { Box, useTheme } from "@mui/material";
|
||||||
import { ItemForQuestions } from "../ItemForQuestions";
|
import { ItemForQuestions } from "../ItemForQuestions";
|
||||||
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "../../StepButtonsBlock";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { MinifiedData, QuestionKeys, SelectedQuestions } from "../../types";
|
import { MinifiedData, QuestionKeys, SelectedQuestions } from "../../types";
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { CustomRadioGroup } from "../../../../../../components/CustomRadioGroup/CustomRadioGroup";
|
import { CustomRadioGroup } from "../../../../../../components/CustomRadioGroup/CustomRadioGroup";
|
||||||
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "../../StepButtonsBlock";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { MinifiedData, TagKeys } from "../../types";
|
import { MinifiedData, TagKeys } from "../../types";
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ interface Props {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AmoRemoveAccount: FC<Props> = ({
|
export const RemoveAccount: FC<Props> = ({
|
||||||
stopThisPage,
|
stopThisPage,
|
||||||
handleCloseModal,
|
handleCloseModal,
|
||||||
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
import { FC } from "react";
|
|
||||||
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
|
||||||
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
|
|
||||||
import { SettingItem } from "./SettingItem/SettingItem";
|
|
||||||
import { SelectedQuestions, SelectedTags } from "../types";
|
|
||||||
|
|
||||||
type AmoSettingsBlockProps = {
|
|
||||||
stepTitles: string[];
|
|
||||||
setStep: (value: number) => void;
|
|
||||||
setIsSettingsBlock: (value: boolean) => void;
|
|
||||||
selectedFunnel: string | null;
|
|
||||||
selectedStage: string | null;
|
|
||||||
selectedDealUser: string | null;
|
|
||||||
selectedQuestions: SelectedQuestions;
|
|
||||||
selectedTags: SelectedTags;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AmoSettingsBlock: FC<AmoSettingsBlockProps> = ({
|
|
||||||
stepTitles,
|
|
||||||
setStep,
|
|
||||||
setIsSettingsBlock,
|
|
||||||
selectedFunnel,
|
|
||||||
selectedDealUser,
|
|
||||||
selectedStage,
|
|
||||||
selectedQuestions,
|
|
||||||
selectedTags,
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
height: "100%",
|
|
||||||
flexGrow: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
marginTop: "10px",
|
|
||||||
width: "100%",
|
|
||||||
height: "443px",
|
|
||||||
borderRadius: "10px",
|
|
||||||
padding: " 0 20px",
|
|
||||||
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
|
|
||||||
overflowY: "auto",
|
|
||||||
flexGrow: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{stepTitles &&
|
|
||||||
stepTitles.map((title, index) => (
|
|
||||||
<SettingItem
|
|
||||||
step={index}
|
|
||||||
title={title}
|
|
||||||
setIsSettingsBlock={setIsSettingsBlock}
|
|
||||||
setStep={setStep}
|
|
||||||
selectedDealUser={selectedDealUser}
|
|
||||||
selectedFunnel={selectedFunnel}
|
|
||||||
selectedStage={selectedStage}
|
|
||||||
selectedQuestions={selectedQuestions}
|
|
||||||
selectedTags={selectedTags}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
marginTop: "20px",
|
|
||||||
alignSelf: "end",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<StepButtonsBlock
|
|
||||||
onSmallBtnClick={() => setIsSettingsBlock(false)}
|
|
||||||
isLargeBtnMissing={true}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { Box, useMediaQuery, useTheme } from "@mui/material";
|
||||||
|
import { StepButtonsBlock } from "../StepButtonsBlock";
|
||||||
|
import { SettingItem } from "./SettingItem/SettingItem";
|
||||||
|
import { SelectedQuestions, SelectedTags } from "../types";
|
||||||
|
|
||||||
|
type AmoSettingsBlockProps = {
|
||||||
|
stepTitles: string[];
|
||||||
|
setStep: (value: number) => void;
|
||||||
|
setIsSettingsBlock: (value: boolean) => void;
|
||||||
|
selectedFunnel: string | null;
|
||||||
|
selectedStage: string | null;
|
||||||
|
selectedDealUser: string | null;
|
||||||
|
selectedQuestions: SelectedQuestions;
|
||||||
|
selectedTags: SelectedTags;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SettingsBlock: FC<AmoSettingsBlockProps> = ({
|
||||||
|
stepTitles,
|
||||||
|
setStep,
|
||||||
|
setIsSettingsBlock,
|
||||||
|
selectedFunnel,
|
||||||
|
selectedDealUser,
|
||||||
|
selectedStage,
|
||||||
|
selectedQuestions,
|
||||||
|
selectedTags,
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ flexGrow: 1, width: "100%" }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100%",
|
||||||
|
flexGrow: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
marginTop: "10px",
|
||||||
|
width: "100%",
|
||||||
|
height: "443px",
|
||||||
|
borderRadius: "10px",
|
||||||
|
padding: " 0 20px",
|
||||||
|
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
|
||||||
|
overflowY: "auto",
|
||||||
|
flexGrow: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{stepTitles &&
|
||||||
|
stepTitles.map((title, index) => (
|
||||||
|
<SettingItem
|
||||||
|
step={index}
|
||||||
|
title={title}
|
||||||
|
setIsSettingsBlock={setIsSettingsBlock}
|
||||||
|
setStep={setStep}
|
||||||
|
selectedDealUser={selectedDealUser}
|
||||||
|
selectedFunnel={selectedFunnel}
|
||||||
|
selectedStage={selectedStage}
|
||||||
|
selectedQuestions={selectedQuestions}
|
||||||
|
selectedTags={selectedTags}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
marginTop: "20px",
|
||||||
|
alignSelf: "end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StepButtonsBlock
|
||||||
|
onSmallBtnClick={() => setIsSettingsBlock(false)}
|
||||||
|
isLargeBtnMissing={true}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
383
src/pages/IntegrationsPage/IntegrationsModal/Amo/SwitchPages.tsx
Normal file
383
src/pages/IntegrationsPage/IntegrationsModal/Amo/SwitchPages.tsx
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
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";
|
||||||
|
import { enqueueSnackbar } from "notistack";
|
||||||
|
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
|
||||||
|
import { RemoveAccount } from "./RemoveAccount";
|
||||||
|
import { DeleteTagQuestion } from "./DeleteTagQuestion";
|
||||||
|
import { AmoLogin } from "./AmoLogin";
|
||||||
|
import { Pipelines } from "./Pipelines";
|
||||||
|
import { PipelineSteps } from "./PipelineSteps";
|
||||||
|
import { DealPerformers } from "./DealPerformers";
|
||||||
|
import { AmoTags } from "./Tags/AmoTags";
|
||||||
|
import { AmoQuestions } from "./Questions/AmoQuestions";
|
||||||
|
import { ModalTitle } from "./ModalTitle";
|
||||||
|
import { SettingsBlock } from "./SettingsBlock/SettingsBlock";
|
||||||
|
import { AccountInfo } from "./AccountInfo";
|
||||||
|
import { useAmoIntegration } from "./useAmoIntegration";
|
||||||
|
import { MinifiedData, QuestionKeys, TagKeys, TagQuestionHC } from "./types";
|
||||||
|
import { Quiz } from "@/model/quiz/quiz";
|
||||||
|
import { AccountResponse, setIntegrationRules, updateIntegrationRules } from "@/api/integration";
|
||||||
|
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
|
||||||
|
import { UntypedQuizQuestion } from "@/model/questionTypes/shared";
|
||||||
|
|
||||||
|
const FCTranslate = {
|
||||||
|
"name": "имя",
|
||||||
|
"email": "почта",
|
||||||
|
"phone": "телефон",
|
||||||
|
"text": "номер",
|
||||||
|
"address": "адрес",
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
quiz: Quiz;
|
||||||
|
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion)[];
|
||||||
|
firstRules: boolean;
|
||||||
|
accountInfo: AccountResponse | null;
|
||||||
|
arrayOfPipelines: MinifiedData[];
|
||||||
|
arrayOfPipelinesSteps: MinifiedData[];
|
||||||
|
arrayOfUsers: MinifiedData[];
|
||||||
|
arrayOfTags: MinifiedData[];
|
||||||
|
arrayOfFields: MinifiedData[];
|
||||||
|
selectedPipeline: string | null;
|
||||||
|
selectedCurrentFields: MinifiedData[];
|
||||||
|
selectedPipelineStep: string | null;
|
||||||
|
selectedDealUser: string | null;
|
||||||
|
setSelectedPipeline:any;
|
||||||
|
setSelectedPipelineStep:any;
|
||||||
|
setSelectedDealPerformer:any;
|
||||||
|
selectedTags:any;
|
||||||
|
setSelectedTags:any;
|
||||||
|
selectedQuestions:any;
|
||||||
|
setSelectedQuestions:any;
|
||||||
|
setPageOfPipelines:any;
|
||||||
|
setPageOfPipelinesSteps:any;
|
||||||
|
setPageOfUsers:any;
|
||||||
|
setPageOfTags:any;
|
||||||
|
setSelectedCurrentFields:any;
|
||||||
|
handleCloseModal:any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SwitchPages = ({
|
||||||
|
quiz,
|
||||||
|
questions,
|
||||||
|
firstRules,
|
||||||
|
accountInfo,
|
||||||
|
arrayOfPipelines,
|
||||||
|
arrayOfPipelinesSteps,
|
||||||
|
arrayOfUsers,
|
||||||
|
arrayOfTags,
|
||||||
|
arrayOfFields,
|
||||||
|
selectedPipeline,
|
||||||
|
setSelectedPipeline,
|
||||||
|
selectedCurrentFields,
|
||||||
|
selectedPipelineStep,
|
||||||
|
setSelectedPipelineStep,
|
||||||
|
selectedDealUser,
|
||||||
|
setSelectedDealPerformer,
|
||||||
|
selectedTags,
|
||||||
|
setSelectedTags,
|
||||||
|
selectedQuestions,
|
||||||
|
setSelectedQuestions,
|
||||||
|
setPageOfPipelines,
|
||||||
|
setPageOfPipelinesSteps,
|
||||||
|
setPageOfUsers,
|
||||||
|
setPageOfTags,
|
||||||
|
setSelectedCurrentFields,
|
||||||
|
handleCloseModal,
|
||||||
|
|
||||||
|
}: Props) => {
|
||||||
|
const [step, setStep] = useState(0)
|
||||||
|
const [specialPage, setSpecialPage] = useState<"deleteCell" | "removeAccount" | "settingsBlock" | "accountInfo" | "amoLogin" | "">("")
|
||||||
|
const [openDelete, setOpenDelete] = useState<TagQuestionHC | null>(null);
|
||||||
|
|
||||||
|
|
||||||
|
const minifiedQuestions = useMemo(
|
||||||
|
() =>
|
||||||
|
questions
|
||||||
|
.filter((q) => q.type !== "result" && q.type !== null)
|
||||||
|
.map(({ backendId, title }) => ({
|
||||||
|
id: backendId.toString() as string,
|
||||||
|
title,
|
||||||
|
})),
|
||||||
|
[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({
|
||||||
|
id: key,
|
||||||
|
title: FCTranslate[key],
|
||||||
|
entity: "Contact",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
[quiz]
|
||||||
|
);
|
||||||
|
const handleAddTagQuestion = (scope: QuestionKeys | TagKeys, id: string, type: "question" | "tag") => {
|
||||||
|
if (!scope || !id) return;
|
||||||
|
|
||||||
|
if (type === "tag") {
|
||||||
|
setSelectedTags((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[scope]: [...prevState[scope as TagKeys], id],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "question") {
|
||||||
|
const q = questions.find(e => e.backendId === Number(id))
|
||||||
|
setSelectedQuestions((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[scope]: [...prevState[scope as QuestionKeys], {
|
||||||
|
id,
|
||||||
|
title: q?.title || "вопрос",
|
||||||
|
entity: scope,
|
||||||
|
}],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteTagQuestion = () => {
|
||||||
|
if (openDelete === null || !openDelete.scope || !openDelete.id || !openDelete.type) return;
|
||||||
|
if (openDelete.type === "tag") {
|
||||||
|
let newArray = selectedTags[openDelete.scope];
|
||||||
|
const index = newArray.indexOf(openDelete.id);
|
||||||
|
if (index !== -1) newArray.splice(index, 1);
|
||||||
|
|
||||||
|
setSelectedTags((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[openDelete.scope]: newArray,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openDelete.type === "question") {
|
||||||
|
let newArray = selectedQuestions
|
||||||
|
newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(e => e.id !== openDelete.id)
|
||||||
|
// let index = -1
|
||||||
|
// selectedQuestions[openDelete.scope].forEach((e, i) => {
|
||||||
|
// if (e.subTitle === openDelete.id) index = i
|
||||||
|
// })
|
||||||
|
// if (index !== -1) newArray.splice(index, 1);
|
||||||
|
// setSelectedQuestions((prevState) => ({
|
||||||
|
// ...prevState,
|
||||||
|
// [openDelete.scope]: newArray,
|
||||||
|
// }));
|
||||||
|
setSelectedQuestions(newArray);
|
||||||
|
setSelectedCurrentFields(selectedCurrentFields.filter(e => e.id !== openDelete.id));
|
||||||
|
|
||||||
|
}
|
||||||
|
setOpenDelete(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleNextStep = () => {
|
||||||
|
setStep((prevState) => prevState + 1);
|
||||||
|
};
|
||||||
|
const handlePrevStep = () => {
|
||||||
|
setStep((prevState) => prevState - 1);
|
||||||
|
};
|
||||||
|
const handleSave = () => {
|
||||||
|
if (quiz?.backendId === undefined) return;
|
||||||
|
if (selectedPipeline === null) return enqueueSnackbar("Выберите воронку");
|
||||||
|
if (selectedPipeline === null) return enqueueSnackbar("Выберите этап воронки");
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
PipelineID: Number(selectedPipeline),
|
||||||
|
StepID: Number(selectedPipelineStep),
|
||||||
|
PerformerID: Number(selectedDealUser),
|
||||||
|
// FieldsRule: questionsBackend,
|
||||||
|
TagsToAdd: selectedTags,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FieldsRule = {
|
||||||
|
Company: { QuestionID: {} },
|
||||||
|
Lead: { QuestionID: {} },
|
||||||
|
Customer: { QuestionID: {} },
|
||||||
|
Contact: {
|
||||||
|
QuestionID: {},
|
||||||
|
ContactRuleMap: {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let key in FieldsRule) {
|
||||||
|
selectedQuestions[key as QuestionKeys].forEach((data) => {
|
||||||
|
FieldsRule[key as QuestionKeys].QuestionID[data.id] = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedCurrentFields.forEach((data) => {
|
||||||
|
if (data.entity === "Contact") {
|
||||||
|
FieldsRule.Contact.ContactRuleMap[data.id] = Number(data.amoId)
|
||||||
|
} else {
|
||||||
|
FieldsRule[data.entity].QuestionID[data.id] = Number(data.amoId) || 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
for (let key in body.TagsToAdd) {
|
||||||
|
body.TagsToAdd[key as TagKeys] = body.TagsToAdd[key as TagKeys].map((id) => Number(id));
|
||||||
|
}
|
||||||
|
body.FieldsRule = FieldsRule;
|
||||||
|
|
||||||
|
// if (firstRules) {
|
||||||
|
// setIntegrationRules(quiz.backendId.toString(), body);
|
||||||
|
// } else {
|
||||||
|
// updateIntegrationRules(quiz.backendId.toString(), body);
|
||||||
|
// }
|
||||||
|
|
||||||
|
handleCloseModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const closeSpecialPage = () => setSpecialPage("")
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
title: "Выбор воронки",
|
||||||
|
desc: "На этом этапе вы можете выбрать нужную воронку и ответственного за сделку",
|
||||||
|
isSettingsAvailable: true,
|
||||||
|
component: (
|
||||||
|
<Pipelines
|
||||||
|
users={arrayOfUsers}
|
||||||
|
pipelines={arrayOfPipelines}
|
||||||
|
handlePrevStep={handlePrevStep}
|
||||||
|
handleNextStep={handleNextStep}
|
||||||
|
selectedDealUser={selectedDealUser}
|
||||||
|
setSelectedDealPerformer={setSelectedDealPerformer}
|
||||||
|
selectedPipeline={selectedPipeline}
|
||||||
|
setSelectedPipeline={setSelectedPipeline}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Выбор этапа воронки",
|
||||||
|
desc: "На этом этапе вы можете выбрать нужный этап и ответственного за сделку",
|
||||||
|
isSettingsAvailable: true,
|
||||||
|
component: (
|
||||||
|
<PipelineSteps
|
||||||
|
users={arrayOfUsers}
|
||||||
|
selectedDealUser={selectedDealUser}
|
||||||
|
selectedStep={selectedPipelineStep}
|
||||||
|
steps={arrayOfPipelinesSteps}
|
||||||
|
setSelectedDealPerformer={setSelectedDealPerformer}
|
||||||
|
setSelectedStep={setSelectedPipelineStep}
|
||||||
|
handlePrevStep={handlePrevStep}
|
||||||
|
handleNextStep={handleNextStep}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Сделка",
|
||||||
|
desc: "На этом этапе вы можете выбрать ответственного за сделку",
|
||||||
|
isSettingsAvailable: true,
|
||||||
|
component: (
|
||||||
|
<DealPerformers
|
||||||
|
handlePrevStep={handlePrevStep}
|
||||||
|
handleNextStep={handleNextStep}
|
||||||
|
users={arrayOfUsers}
|
||||||
|
selectedDealUser={selectedDealUser}
|
||||||
|
setSelectedDealPerformer={setSelectedDealPerformer}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Добавление тегов",
|
||||||
|
isSettingsAvailable: true,
|
||||||
|
component: (
|
||||||
|
<AmoTags
|
||||||
|
tagsItems={arrayOfTags}
|
||||||
|
selectedTags={selectedTags}
|
||||||
|
openDelete={setOpenDelete}
|
||||||
|
handleScroll={() => { }}
|
||||||
|
handleAddTag={handleAddTagQuestion}
|
||||||
|
handlePrevStep={handlePrevStep}
|
||||||
|
handleNextStep={handleNextStep}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Соотнесение вопросов и сущностей",
|
||||||
|
isSettingsAvailable: true,
|
||||||
|
component: (
|
||||||
|
<AmoQuestions
|
||||||
|
setSelectedCurrentFields={setSelectedCurrentFields}
|
||||||
|
fieldsItems={arrayOfFields}
|
||||||
|
selectedCurrentFields={selectedCurrentFields}
|
||||||
|
questionsItems={minifiedQuestions}
|
||||||
|
selectedQuestions={selectedQuestions}
|
||||||
|
openDelete={setOpenDelete}
|
||||||
|
handleAddQuestion={handleAddTagQuestion}
|
||||||
|
handlePrevStep={handlePrevStep}
|
||||||
|
handleNextStep={handleSave}
|
||||||
|
FieldsAllowedFC={FieldsAllowedFC}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const stepTitles = steps.map((step) => step.title);
|
||||||
|
|
||||||
|
switch (specialPage) {
|
||||||
|
case "deleteCell":
|
||||||
|
return <DeleteTagQuestion
|
||||||
|
close={closeSpecialPage}
|
||||||
|
deleteItem={handleDeleteTagQuestion}
|
||||||
|
/>
|
||||||
|
case "removeAccount":
|
||||||
|
return <RemoveAccount
|
||||||
|
handleCloseModal={closeSpecialPage}
|
||||||
|
stopThisPage={closeSpecialPage}
|
||||||
|
/>
|
||||||
|
case "settingsBlock":
|
||||||
|
return <SettingsBlock
|
||||||
|
stepTitles={stepTitles}
|
||||||
|
setIsSettingsBlock={setIsSettingsBlock}
|
||||||
|
setStep={setStep}
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
case "amoLogin": return <AmoLogin handleNextStep={handleNextStep} />
|
||||||
|
case "accountInfo": return <AmoAccountInfo
|
||||||
|
handleNextStep={handleNextStep}
|
||||||
|
accountInfo={accountInfo}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
default: <Box sx={{ flexGrow: 1, width: "100%" }}>{steps[step].component}</Box>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const S = <ModalTitle
|
||||||
|
// step={1}
|
||||||
|
// steps={2}
|
||||||
|
// isSettingsBlock={true}
|
||||||
|
// setIsSettingsBlock={setIsSettingsBlock}
|
||||||
|
// setStep={setStep}
|
||||||
|
// startRemoveAccount={() => setSpecialPage("removeAccount")}
|
||||||
|
// />
|
||||||
|
|
||||||
|
|
||||||
|
// title: accountInfo ? "Информация об аккаунте" : "Авторизация в аккаунте",
|
||||||
|
// isSettingsAvailable: false,
|
||||||
|
// component: accountInfo ? (
|
||||||
|
// <AmoAccountInfo
|
||||||
|
// handleNextStep={handleNextStep}
|
||||||
|
// accountInfo={accountInfo}
|
||||||
|
// />
|
||||||
|
// ) : (
|
||||||
|
// <AmoLogin handleNextStep={handleNextStep} />
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { ItemsSelectionView } from "../AmoQuestions/ItemsSelectionView/ItemsSelectionView";
|
import { ItemsSelectionView } from "../Questions/ItemsSelectionView/ItemsSelectionView";
|
||||||
import { TagsDetailsView } from "./TagsDetailsView/TagsDetailsView";
|
import { TagsDetailsView } from "./TagsDetailsView/TagsDetailsView";
|
||||||
import { MinifiedData, QuestionKeys, SelectedTags, TagKeys, TagQuestionHC } from "../types";
|
import { MinifiedData, QuestionKeys, SelectedTags, TagKeys, TagQuestionHC } from "../types";
|
||||||
import { DataConstrictor } from "../Components/DataConstrictor";
|
import { DataConstrictor } from "../Components/DataConstrictor";
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
|
import { StepButtonsBlock } from "../../StepButtonsBlock";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Item } from "../../AmoQuestions/Item/Item";
|
import { Item } from "../../Questions/Item/Item";
|
||||||
import { MinifiedData, SelectedTags, TagKeys } from "../../types";
|
import { MinifiedData, SelectedTags, TagKeys } from "../../types";
|
||||||
|
|
||||||
type TagsDetailsViewProps = {
|
type TagsDetailsViewProps = {
|
||||||
166
src/pages/IntegrationsPage/IntegrationsModal/Amo/index.tsx
Normal file
166
src/pages/IntegrationsPage/IntegrationsModal/Amo/index.tsx
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import { FC, useState } from "react";
|
||||||
|
import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box, Skeleton } from "@mui/material";
|
||||||
|
import { useQuestions } from "@/stores/questions/hooks";
|
||||||
|
import { redirect, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
|
||||||
|
import { useAmoIntegration } from "./useAmoIntegration";
|
||||||
|
import { MinifiedData } from "./types";
|
||||||
|
import { Quiz } from "@/model/quiz/quiz";
|
||||||
|
import { SwitchPages } from "./SwitchPages";
|
||||||
|
|
||||||
|
type IntegrationsModalProps = {
|
||||||
|
isModalOpen: boolean;
|
||||||
|
handleCloseModal: () => void;
|
||||||
|
companyName: string | null;
|
||||||
|
quiz: Quiz;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleCloseModal, companyName, quiz }) => {
|
||||||
|
//Если нет контекста квиза, то и делать на этой страничке нечего
|
||||||
|
if (quiz.backendId === undefined) {
|
||||||
|
redirect("/list");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||||
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
|
|
||||||
|
const { questions } = useQuestions();
|
||||||
|
|
||||||
|
const [isTryRemoveAccount, setIsTryRemoveAccount] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
isLoadingPage,
|
||||||
|
firstRules,
|
||||||
|
accountInfo,
|
||||||
|
arrayOfPipelines,
|
||||||
|
arrayOfPipelinesSteps,
|
||||||
|
arrayOfUsers,
|
||||||
|
arrayOfTags,
|
||||||
|
arrayOfFields,
|
||||||
|
selectedPipeline,
|
||||||
|
setSelectedPipeline,
|
||||||
|
selectedCurrentFields,
|
||||||
|
selectedPipelineStep,
|
||||||
|
setSelectedPipelineStep,
|
||||||
|
selectedDealUser,
|
||||||
|
setSelectedDealPerformer,
|
||||||
|
questionsBackend,
|
||||||
|
selectedTags,
|
||||||
|
setSelectedTags,
|
||||||
|
selectedQuestions,
|
||||||
|
setSelectedQuestions,
|
||||||
|
setPageOfPipelines,
|
||||||
|
setPageOfPipelinesSteps,
|
||||||
|
setPageOfUsers,
|
||||||
|
setPageOfTags,
|
||||||
|
setSelectedCurrentFields,
|
||||||
|
} = useAmoIntegration({
|
||||||
|
quizID: quiz.backendId,
|
||||||
|
isModalOpen,
|
||||||
|
isTryRemoveAccount,
|
||||||
|
questions,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={isModalOpen}
|
||||||
|
onClose={handleCloseModal}
|
||||||
|
fullWidth
|
||||||
|
// fullScreen={isMobile}
|
||||||
|
PaperProps={{
|
||||||
|
sx: {
|
||||||
|
maxWidth: isTablet ? "100%" : "920px",
|
||||||
|
maxHeight: isTablet ? "100%" : "680px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "68px",
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: isMobile ? "20px" : "24px",
|
||||||
|
fontWeight: "500",
|
||||||
|
padding: "20px",
|
||||||
|
color: theme.palette.grey2.main,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Интеграция с {companyName ? companyName : "партнером"}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleCloseModal}
|
||||||
|
sx={{
|
||||||
|
width: "12px",
|
||||||
|
height: "12px",
|
||||||
|
position: "absolute",
|
||||||
|
right: "15px",
|
||||||
|
top: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloseIcon sx={{ width: "12px", height: "12px", transform: "scale(1.5)" }} />
|
||||||
|
</IconButton>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: isTablet ? "100%" : "920px",
|
||||||
|
height: "600px",
|
||||||
|
padding: "15px 20px 15px",
|
||||||
|
flexGrow: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isLoadingPage ?
|
||||||
|
<Skeleton
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
transform: "none",
|
||||||
|
}}
|
||||||
|
/> :
|
||||||
|
<SwitchPages
|
||||||
|
quiz={quiz}
|
||||||
|
questions={questions}
|
||||||
|
firstRules={firstRules}
|
||||||
|
accountInfo={accountInfo}
|
||||||
|
arrayOfPipelines={arrayOfPipelines}
|
||||||
|
arrayOfPipelinesSteps={arrayOfPipelinesSteps}
|
||||||
|
arrayOfUsers={arrayOfUsers}
|
||||||
|
arrayOfTags={arrayOfTags}
|
||||||
|
arrayOfFields={arrayOfFields}
|
||||||
|
selectedPipeline={selectedPipeline}
|
||||||
|
setSelectedPipeline={setSelectedPipeline}
|
||||||
|
selectedCurrentFields={selectedCurrentFields}
|
||||||
|
selectedPipelineStep={selectedPipelineStep}
|
||||||
|
setSelectedPipelineStep={setSelectedPipelineStep}
|
||||||
|
selectedDealUser={selectedDealUser}
|
||||||
|
setSelectedDealPerformer={setSelectedDealPerformer}
|
||||||
|
selectedTags={selectedTags}
|
||||||
|
setSelectedTags={setSelectedTags}
|
||||||
|
selectedQuestions={selectedQuestions}
|
||||||
|
setSelectedQuestions={setSelectedQuestions}
|
||||||
|
setPageOfPipelines={setPageOfPipelines}
|
||||||
|
setPageOfPipelinesSteps={setPageOfPipelinesSteps}
|
||||||
|
setPageOfUsers={setPageOfUsers}
|
||||||
|
setPageOfTags={setPageOfTags}
|
||||||
|
setSelectedCurrentFields={setSelectedCurrentFields}
|
||||||
|
handleCloseModal={handleCloseModal}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</Box>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const diffArr = (arr_A: MinifiedData[], arr_B: MinifiedData[]) => {
|
||||||
|
return arr_A.filter(person_A => !arr_B.some(person_B => person_A.id === person_B.id));
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
getFields,
|
getFields,
|
||||||
} from "@/api/integration";
|
} from "@/api/integration";
|
||||||
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
|
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
|
||||||
|
import { UntypedQuizQuestion } from "@/model/questionTypes/shared";
|
||||||
|
|
||||||
const SIZE = 275;
|
const SIZE = 275;
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ interface Props {
|
|||||||
isModalOpen: boolean;
|
isModalOpen: boolean;
|
||||||
isTryRemoveAccount: boolean;
|
isTryRemoveAccount: boolean;
|
||||||
quizID: number;
|
quizID: number;
|
||||||
questions: AnyTypedQuizQuestion
|
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const FCTranslate = {
|
const FCTranslate = {
|
||||||
@ -151,6 +152,22 @@ export const useAmoIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, que
|
|||||||
|
|
||||||
}, [isModalOpen, isTryRemoveAccount]);
|
}, [isModalOpen, isTryRemoveAccount]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const transletedQuestions = {}
|
||||||
|
|
||||||
|
Object.keys(selectedQuestions).forEach((column) => {
|
||||||
|
selectedQuestions[column].forEach((minifiedData) => {
|
||||||
|
const q = questions.find(e => e.backendId === Number(minifiedData.id)) || {}
|
||||||
|
transletedQuestions[column] = {
|
||||||
|
...minifiedData,
|
||||||
|
title: q.title || transletedQuestions[column].title
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
setSelectedQuestions(transletedQuestions)
|
||||||
|
}, [questions])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getPipelines({
|
getPipelines({
|
||||||
page: pageOfPipelines,
|
page: pageOfPipelines,
|
||||||
|
|||||||
@ -16,7 +16,7 @@ const AnalyticsModal = lazy(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const AmoCRMModal = lazy(() =>
|
const AmoCRMModal = lazy(() =>
|
||||||
import("../IntegrationsModal/Amo/AmoCRMModal").then((module) => ({
|
import("../IntegrationsModal/Amo").then((module) => ({
|
||||||
default: module.AmoCRMModal,
|
default: module.AmoCRMModal,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user