WIP... realized pipelines, users, removed utm, refactored modals with lazy

This commit is contained in:
aleksandr-raw 2024-05-22 01:29:33 +04:00
parent 73fa046cc8
commit a66a4764cf
14 changed files with 234 additions and 322 deletions

@ -21,7 +21,7 @@ export type TagsResponse = {
count: number; count: number;
items: Tag[]; items: Tag[];
}; };
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/amocrm/amocrm`; const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/amocrm`;
export const getTags = async ({ export const getTags = async ({
page, page,
@ -112,3 +112,37 @@ export const getSteps = async ({
return [null, `Не удалось получить список шагов. ${error}`]; return [null, `Не удалось получить список шагов. ${error}`];
} }
}; };
export type Pipeline = {
ID: number;
AmoID: number;
AccountID: number;
Name: string;
IsArchive: boolean;
Deleted: boolean;
CreatedAt: number;
};
export type PipelinesResponse = {
count: number;
items: Pipeline[];
};
export const getPipelines = async ({
page,
size,
}: PaginationRequest): Promise<[PipelinesResponse | null, string?]> => {
try {
const pipelinesResponse = await makeRequest<
PaginationRequest,
PipelinesResponse
>({
method: "GET",
url: `${API_URL}/pipelines?page=${page}&size=${size}`,
});
return [pipelinesResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось получить список воронок. ${error}`];
}
};

@ -7,9 +7,11 @@ import Box from "@mui/material/Box";
import CheckboxIcon from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
import { Typography, useTheme } from "@mui/material"; import { Typography, useTheme } from "@mui/material";
import { import {
getPipelines,
getSteps, getSteps,
getTags, getTags,
PaginationRequest, PaginationRequest,
Pipeline,
Step, Step,
Tag, Tag,
} from "@api/integration"; } from "@api/integration";
@ -37,6 +39,7 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [tags, setTags] = useState<Tag[]>([]); const [tags, setTags] = useState<Tag[]>([]);
const [steps, setSteps] = useState<Step[]>([]); const [steps, setSteps] = useState<Step[]>([]);
const [pipelines, setPipelines] = useState<Pipeline[]>([]);
const [hasMoreItems, setHasMoreItems] = useState(true); const [hasMoreItems, setHasMoreItems] = useState(true);
const boxRef = useRef(null); const boxRef = useRef(null);
@ -90,6 +93,22 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
setIsLoading(false); setIsLoading(false);
}); });
} }
if (type === "typePipelines" && hasMoreItems) {
setIsLoading(true);
const pagination: PaginationRequest = {
page: page,
size: SIZE,
};
getPipelines(pagination).then(([response]) => {
if (response && response.items !== null) {
setPipelines((prevItems) => [...prevItems, ...response.items]);
if (response.items.length < SIZE) {
setHasMoreItems(false);
}
}
setIsLoading(false);
});
}
}, [page, type, hasMoreItems, pipelineId]); }, [page, type, hasMoreItems, pipelineId]);
const formControlLabels = useMemo(() => { const formControlLabels = useMemo(() => {
@ -123,7 +142,6 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
icon={<CheckboxIcon isRounded />} icon={<CheckboxIcon isRounded />}
/> />
} }
// label={item.Name}
label={ label={
<Box sx={{ display: "flex", flexDirection: "column" }}> <Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography sx={{ color: `${item.Color}` }}> <Typography sx={{ color: `${item.Color}` }}>
@ -171,6 +189,41 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
/> />
)); ));
} }
if (type === "typePipelines" && pipelines && pipelines.length !== 0) {
return pipelines.map((pipeline) => (
<FormControlLabel
key={pipeline.ID}
sx={{
color: "black",
padding: "15px",
borderBottom: `1px solid ${theme.palette.background.default}`,
display: "flex",
justifyContent: "space-between",
borderRadius: "12px",
margin: 0,
backgroundColor:
currentValue === pipeline.Name
? theme.palette.background.default
: theme.palette.common.white,
}}
value={pipeline.Name}
control={
<Radio
checkedIcon={
<CheckboxIcon
checked
isRounded
color={theme.palette.brightPurple.main}
/>
}
icon={<CheckboxIcon isRounded />}
/>
}
label={pipeline.Name}
labelPlacement={"start"}
/>
));
}
return ( return (
<Box <Box
sx={{ sx={{
@ -184,7 +237,7 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
<Typography>Нет элементов</Typography> <Typography>Нет элементов</Typography>
</Box> </Box>
); );
}, [tags, currentValue, type]); }, [tags, steps, currentValue, type, pipelines]);
return ( return (
<Box <Box

@ -35,15 +35,22 @@ export const CustomSelect: FC<CustomSelectProps> = ({
const [hasMoreItems, setHasMoreItems] = useState(true); const [hasMoreItems, setHasMoreItems] = useState(true);
const SIZE = 25; const SIZE = 25;
const ref = useRef<HTMLDivElement | null>(null); const ref = useRef<HTMLDivElement | null>(null);
console.log("page", page); const selectWidth = ref.current ? ref.current.offsetWidth : undefined;
const [savedValue, setSavedValue] = useState<number | null>(null);
const onSelectItem = useCallback( const onSelectItem = useCallback(
(event: SelectChangeEvent<HTMLDivElement>) => { (event: SelectChangeEvent<HTMLDivElement>) => {
const newValue = event.target.value.toString(); const newValue = event.target.value.toString();
const selectedUser = users.find((user) => user.Name === newValue);
if (selectedUser) {
//для сохранения ID выбранного пользователя в стейт или конфиг...
setSavedValue(selectedUser.ID);
}
setCurrentValue(newValue); setCurrentValue(newValue);
setSelectedItem(newValue); setSelectedItem(newValue);
}, },
[setSelectedItem, setCurrentValue], [setSelectedItem, setCurrentValue, setSavedValue, users],
); );
const toggleOpened = useCallback(() => { const toggleOpened = useCallback(() => {
@ -86,9 +93,56 @@ export const CustomSelect: FC<CustomSelectProps> = ({
<MenuItem <MenuItem
key={user.ID} key={user.ID}
value={user.Name} value={user.Name}
sx={{ padding: "12px", zIndex: 2 }} sx={{
padding: "6px 0",
zIndex: 2,
borderTop: "1px solid rgba(154, 154, 175, 0.1)",
width: "auto",
}}
> >
{user.Name} <Box
sx={{
fontSize: "16px",
color: "#4D4D4D",
display: "flex",
flexDirection: isMobile ? "column" : "row",
justifyContent: "space-evenly",
width: "100%",
}}
>
<Typography
sx={{
width: "33%",
borderRight: isMobile
? "none"
: "1px solid rgba(154, 154, 175, 0.1)",
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
}}
>
{user.Name}
</Typography>
<Typography
sx={{
width: "33%",
borderRight: isMobile
? "none"
: "1px solid rgba(154, 154, 175, 0.1)",
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
color: isMobile ? "#9A9AAF" : "#4D4D4D",
}}
>
{user.Email}
</Typography>
<Typography
sx={{
width: "33%",
padding: isMobile ? "5px 0 5px 20px" : "10px 0 10px 20px",
color: isMobile ? "#9A9AAF" : "#4D4D4D",
}}
>
{user.Role}
</Typography>
</Box>
</MenuItem> </MenuItem>
)); ));
} }
@ -162,10 +216,12 @@ export const CustomSelect: FC<CustomSelectProps> = ({
zIndex: 2, zIndex: 2,
maxHeight: "300px", maxHeight: "300px",
overflow: "auto", overflow: "auto",
overflowX: "auto",
maxWidth: selectWidth,
}, },
}, },
}} }}
sx={{ width: "100%" }} sx={{}}
onChange={onSelectItem} onChange={onSelectItem}
onClick={toggleOpened} onClick={toggleOpened}
> >

@ -12,9 +12,8 @@ import { IntegrationStep1 } from "./IntegrationStep1/IntegrationStep1";
import { IntegrationStep2 } from "./IntegrationStep2/IntegrationStep2"; import { IntegrationStep2 } from "./IntegrationStep2/IntegrationStep2";
import { IntegrationStep3 } from "./IntegrationStep3/IntegrationStep3"; import { IntegrationStep3 } from "./IntegrationStep3/IntegrationStep3";
import { IntegrationStep4 } from "./IntegrationStep4/IntegrationStep4"; import { IntegrationStep4 } from "./IntegrationStep4/IntegrationStep4";
import { IntegrationStep5 } from "./IntegrationStep5/IntegrationStep5";
import { IntegrationStep6 } from "./IntegrationStep6/IntegrationStep6"; import { IntegrationStep6 } from "./IntegrationStep6/IntegrationStep6";
import { funnelsMock, performersMock, stagesMock } from "../mocks/MockData"; import { performersMock } from "../mocks/MockData";
import { IntegrationsModalTitle } from "./IntegrationsModalTitle/IntegrationsModalTitle"; import { IntegrationsModalTitle } from "./IntegrationsModalTitle/IntegrationsModalTitle";
import { SettingsBlock } from "./SettingsBlock/SettingsBlock"; import { SettingsBlock } from "./SettingsBlock/SettingsBlock";
import { IntegrationStep7 } from "./IntegrationStep7/IntegrationStep7"; import { IntegrationStep7 } from "./IntegrationStep7/IntegrationStep7";
@ -42,18 +41,17 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
const [step, setStep] = useState<number>(0); const [step, setStep] = useState<number>(0);
const [isSettingsBlock, setIsSettingsBlock] = useState<boolean>(false); const [isSettingsBlock, setIsSettingsBlock] = useState<boolean>(false);
const [selectedFunnelPerformer, setSelectedFunnelPerformer] = useState< const [selectedPipelinePerformer, setSelectedPipelinePerformer] = useState<
string | null string | null
>(null); >(null);
const [selectedFunnel, setSelectedFunnel] = useState<string | null>(null); const [selectedPipeline, setSelectedPipeline] = useState<string | null>(null);
const [selectedStagePerformer, setSelectedStagePerformer] = useState< const [selectedStepsPerformer, setSelectedStepsPerformer] = useState<
string | null string | null
>(null); >(null);
const [selectedStage, setSelectedStage] = useState<string | null>(null); const [selectedStep, setSelectedStep] = useState<string | null>(null);
const [selectedDealPerformer, setSelectedDealPerformer] = useState< const [selectedDealPerformer, setSelectedDealPerformer] = useState<
string | null string | null
>(null); >(null);
const [utmFile, setUtmFile] = useState<File | null>(null);
const [questionEntity, setQuestionEntity] = useState<TQuestionEntity>({ const [questionEntity, setQuestionEntity] = useState<TQuestionEntity>({
contacts: [], contacts: [],
company: [], company: [],
@ -93,12 +91,10 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
<IntegrationStep2 <IntegrationStep2
handlePrevStep={handlePrevStep} handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep} handleNextStep={handleNextStep}
selectedFunnelPerformer={selectedFunnelPerformer} selectedPipelinePerformer={selectedPipelinePerformer}
setSelectedFunnelPerformer={setSelectedFunnelPerformer} setSelectedPipelinePerformer={setSelectedPipelinePerformer}
selectedFunnel={selectedFunnel} selectedPipeline={selectedPipeline}
setSelectedFunnel={setSelectedFunnel} setSelectedPipeline={setSelectedPipeline}
performers={performersMock}
funnels={funnelsMock}
/> />
), ),
}, },
@ -109,13 +105,11 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
<IntegrationStep3 <IntegrationStep3
handlePrevStep={handlePrevStep} handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep} handleNextStep={handleNextStep}
selectedStagePerformer={selectedStagePerformer} selectedStepsPerformer={selectedStepsPerformer}
setSelectedStagePerformer={setSelectedStagePerformer} setSelectedStepsPerformer={setSelectedStepsPerformer}
selectedStage={selectedStage} selectedStep={selectedStep}
setSelectedStage={setSelectedStage} setSelectedStep={setSelectedStep}
performers={performersMock} pipelineId={selectedPipeline}
stages={stagesMock}
pipelineId={selectedFunnel}
/> />
), ),
}, },
@ -132,18 +126,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
/> />
), ),
}, },
{
title: "Добавление utm-меток",
isSettingsAvailable: false,
component: (
<IntegrationStep5
handlePrevStep={handlePrevStep}
handleNextStep={handleNextStep}
utmFile={utmFile}
setUtmFile={setUtmFile}
/>
),
},
{ {
title: "Соотнесение вопросов и сущностей", title: "Соотнесение вопросов и сущностей",
isSettingsAvailable: true, isSettingsAvailable: true,
@ -171,11 +153,11 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
], ],
[ [
questionEntity, questionEntity,
utmFile, // utmFile,
selectedFunnelPerformer, selectedPipelinePerformer,
selectedFunnel, selectedPipeline,
selectedStagePerformer, selectedStepsPerformer,
selectedStage, selectedStep,
selectedDealPerformer, selectedDealPerformer,
tags, tags,
], ],
@ -188,7 +170,7 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
open={isModalOpen} open={isModalOpen}
onClose={handleCloseModal} onClose={handleCloseModal}
fullWidth fullWidth
fullScreen={isMobile} // fullScreen={isMobile}
PaperProps={{ PaperProps={{
sx: { sx: {
maxWidth: isTablet ? "100%" : "920px", maxWidth: isTablet ? "100%" : "920px",
@ -253,11 +235,10 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({
setIsSettingsBlock={setIsSettingsBlock} setIsSettingsBlock={setIsSettingsBlock}
setStep={setStep} setStep={setStep}
selectedDealPerformer={selectedDealPerformer} selectedDealPerformer={selectedDealPerformer}
selectedFunnelPerformer={selectedFunnelPerformer} selectedFunnelPerformer={selectedPipelinePerformer}
selectedFunnel={selectedFunnel} selectedFunnel={selectedPipeline}
selectedStagePerformer={selectedStagePerformer} selectedStagePerformer={selectedStepsPerformer}
selectedStage={selectedStage} selectedStage={selectedStep}
utmFile={utmFile}
questionEntity={questionEntity} questionEntity={questionEntity}
tags={tags} tags={tags}
/> />

@ -7,23 +7,19 @@ import { CustomRadioGroup } from "../../../../components/CustomRadioGroup/Custom
type IntegrationStep2Props = { type IntegrationStep2Props = {
handlePrevStep: () => void; handlePrevStep: () => void;
handleNextStep: () => void; handleNextStep: () => void;
selectedFunnelPerformer: string | null; selectedPipelinePerformer: string | null;
setSelectedFunnelPerformer: (value: string | null) => void; setSelectedPipelinePerformer: (value: string | null) => void;
selectedFunnel: string | null; selectedPipeline: string | null;
setSelectedFunnel: (value: string | null) => void; setSelectedPipeline: (value: string | null) => void;
performers: string[];
funnels: string[];
}; };
export const IntegrationStep2: FC<IntegrationStep2Props> = ({ export const IntegrationStep2: FC<IntegrationStep2Props> = ({
handlePrevStep, handlePrevStep,
handleNextStep, handleNextStep,
selectedFunnelPerformer, selectedPipelinePerformer,
setSelectedFunnelPerformer, setSelectedPipelinePerformer,
selectedFunnel, selectedPipeline,
setSelectedFunnel, setSelectedPipeline,
performers,
funnels,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -40,8 +36,8 @@ export const IntegrationStep2: FC<IntegrationStep2Props> = ({
> >
<Box sx={{ width: "100%", marginTop: "20px", zIndex: 3 }}> <Box sx={{ width: "100%", marginTop: "20px", zIndex: 3 }}>
<CustomSelect <CustomSelect
selectedItem={selectedFunnelPerformer} selectedItem={selectedPipelinePerformer}
setSelectedItem={setSelectedFunnelPerformer} setSelectedItem={setSelectedPipelinePerformer}
type={"typeUsers"} type={"typeUsers"}
/> />
</Box> </Box>
@ -54,8 +50,9 @@ export const IntegrationStep2: FC<IntegrationStep2Props> = ({
}} }}
> >
<CustomRadioGroup <CustomRadioGroup
selectedValue={selectedFunnel} selectedValue={selectedPipeline}
setSelectedValue={setSelectedFunnel} setSelectedValue={setSelectedPipeline}
type={"typePipelines"}
/> />
</Box> </Box>
<Box <Box

@ -7,22 +7,20 @@ import { CustomRadioGroup } from "../../../../components/CustomRadioGroup/Custom
type IntegrationStep3Props = { type IntegrationStep3Props = {
handlePrevStep: () => void; handlePrevStep: () => void;
handleNextStep: () => void; handleNextStep: () => void;
selectedStagePerformer: string | null; selectedStepsPerformer: string | null;
setSelectedStagePerformer: (value: string | null) => void; setSelectedStepsPerformer: (value: string | null) => void;
selectedStage: string | null; selectedStep: string | null;
setSelectedStage: (value: string | null) => void; setSelectedStep: (value: string | null) => void;
performers: string[];
stages: string[];
pipelineId: string | null; pipelineId: string | null;
}; };
export const IntegrationStep3: FC<IntegrationStep3Props> = ({ export const IntegrationStep3: FC<IntegrationStep3Props> = ({
handlePrevStep, handlePrevStep,
handleNextStep, handleNextStep,
selectedStagePerformer, selectedStepsPerformer,
setSelectedStagePerformer, setSelectedStepsPerformer,
selectedStage, selectedStep,
setSelectedStage, setSelectedStep,
pipelineId, pipelineId,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
@ -41,9 +39,9 @@ export const IntegrationStep3: FC<IntegrationStep3Props> = ({
> >
<Box sx={{ width: "100%", marginTop: "20px", zIndex: 3 }}> <Box sx={{ width: "100%", marginTop: "20px", zIndex: 3 }}>
<CustomSelect <CustomSelect
selectedItem={selectedStagePerformer} selectedItem={selectedStepsPerformer}
type={"typeUsers"} type={"typeUsers"}
setSelectedItem={setSelectedStagePerformer} setSelectedItem={setSelectedStepsPerformer}
/> />
</Box> </Box>
<Box <Box
@ -57,8 +55,8 @@ export const IntegrationStep3: FC<IntegrationStep3Props> = ({
<CustomRadioGroup <CustomRadioGroup
pipelineId={pipelineId} pipelineId={pipelineId}
type={"typeSteps"} type={"typeSteps"}
selectedValue={selectedStage} selectedValue={selectedStep}
setSelectedValue={setSelectedStage} setSelectedValue={setSelectedStep}
/> />
</Box> </Box>
<Box <Box

@ -1,94 +0,0 @@
import {
Box,
ButtonBase,
Typography,
useMediaQuery,
useTheme,
} from "@mui/material";
import UploadIcon from "@icons/UploadIcon";
import { type DragEvent, FC, useRef, useState } from "react";
type TextFormat = "txt" | "docx";
interface CustomFileUploaderProps {
description?: string;
accept?: TextFormat[];
handleImageChange: (file: File) => void;
}
export const CustomFileUploader: FC<CustomFileUploaderProps> = ({
accept,
description,
handleImageChange,
}) => {
const theme = useTheme();
const dropZone = useRef<HTMLDivElement>(null);
const [ready, setReady] = useState(false);
const isMobile = useMediaQuery(theme.breakpoints.down(700));
const handleDragEnter = (event: DragEvent<HTMLDivElement>) => {
event.preventDefault();
setReady(true);
};
const handleDrop = (event: DragEvent<HTMLDivElement>) => {
event.preventDefault();
event.stopPropagation();
const file = event.dataTransfer.files[0];
if (!file) return;
handleImageChange(file);
};
const acceptedFormats = accept
? accept.map((format) => "." + format).join(", ")
: "";
return (
<ButtonBase component="label" sx={{ justifyContent: "flex-start" }}>
<input
onChange={(event) => {
const file = event.target.files?.[0];
if (file) handleImageChange(file);
}}
hidden
accept={acceptedFormats || ".jpg, .jpeg, .png , .gif"}
multiple
type="file"
data-cy="upload-image-input"
/>
<Box
onDragOver={(event: DragEvent<HTMLDivElement>) =>
event.preventDefault()
}
onDrop={handleDrop}
ref={dropZone}
sx={{
width: isMobile ? "100%" : "580px",
padding: isMobile ? "33px" : "33px 10px 33px 55px",
display: "flex",
alignItems: "center",
backgroundColor: theme.palette.background.default,
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
borderRadius: "8px",
gap: "55px",
flexDirection: isMobile ? "column" : "row",
}}
onDragEnter={handleDragEnter}
>
<UploadIcon />
<Box>
<Typography sx={{ color: "#9A9AAF", fontWeight: "bold" }}>
Добавить файл
</Typography>
<Typography
sx={{ color: theme.palette.grey2.main, fontSize: "16px" }}
>
{description || "Принимает JPG, PNG, и GIF формат — максимум 5mb"}
</Typography>
</Box>
</Box>
</ButtonBase>
);
};

@ -1,58 +0,0 @@
import React, { FC } from "react";
import Box from "@mui/material/Box";
import { IconButton, Typography, useTheme } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
type FileBlockProps = {
file: File | null;
setFile?: (file: File | null) => void;
};
export const FileBlock: FC<FileBlockProps> = ({ setFile, file }) => {
const theme = useTheme();
return (
<Box sx={{ display: "flex", gap: "15px", alignItems: "center" }}>
<Typography
sx={{
fontSize: "18px",
fontWeight: "400",
color: theme.palette.grey3.main,
}}
>
Вы загрузили:
</Typography>
<Box
sx={{
display: "flex",
alignItems: "center",
backgroundColor: theme.palette.brightPurple.main,
borderRadius: "8px",
padding: setFile ? "5px 5px 5px 14px" : "5px 14px",
gap: "20px",
}}
>
<Typography
sx={{ color: "white", fontSize: "14px", fontWeight: "400" }}
>
{file?.name}
</Typography>
{setFile && (
<IconButton
onClick={() => setFile(null)}
sx={{
backgroundColor: "#864BD9",
borderRadius: "50%",
width: "24px",
height: "24px",
color: "white",
}}
>
<CloseIcon
sx={{ width: "14px", height: "14px", transform: "scale(1.5)" }}
/>
</IconButton>
)}
</Box>
</Box>
);
};

@ -1,52 +0,0 @@
import { Box, useMediaQuery, useTheme } from "@mui/material";
import React, { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
import File from "@ui_kit/QuizPreview/QuizPreviewQuestionTypes/File";
import { FileBlock } from "./FileBlock/FileBlock";
import { CustomFileUploader } from "./CustomFileUploader/CustomFileUploader";
type IntegrationStep5Props = {
handlePrevStep: () => void;
handleNextStep: () => void;
setUtmFile: (file: File | null) => void;
utmFile: File | null;
};
export const IntegrationStep5: FC<IntegrationStep5Props> = ({
handlePrevStep,
handleNextStep,
utmFile,
setUtmFile,
}) => {
const theme = useTheme();
const upMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Box sx={{ alignSelf: "start", marginTop: "20px" }}>
{utmFile ? (
<FileBlock file={utmFile} setFile={setUtmFile} />
) : (
<CustomFileUploader
description={"Принимает .txt и .docx формат — максимум 100мб"}
accept={["txt", "docx"]}
handleImageChange={setUtmFile}
/>
)}
</Box>
<StepButtonsBlock
onLargeBtnClick={handleNextStep}
onSmallBtnClick={handlePrevStep}
isLargeBtnDisabled={!utmFile}
/>
</Box>
);
};

@ -4,7 +4,6 @@ import { Typography, useMediaQuery, useTheme } from "@mui/material";
import { SettingItemHeader } from "./SettingItemHeader/SettingItemHeader"; import { SettingItemHeader } from "./SettingItemHeader/SettingItemHeader";
import { ResponsiblePerson } from "./ResponsiblePerson/ResponsiblePerson"; import { ResponsiblePerson } from "./ResponsiblePerson/ResponsiblePerson";
import { SelectedParameter } from "./SelectedParameter/SelectedParameter"; import { SelectedParameter } from "./SelectedParameter/SelectedParameter";
import { FileBlock } from "../../IntegrationStep5/FileBlock/FileBlock";
import { TQuestionEntity, TTags } from "../../AmoCRMModal"; import { TQuestionEntity, TTags } from "../../AmoCRMModal";
type SettingItemProps = { type SettingItemProps = {
@ -17,7 +16,6 @@ type SettingItemProps = {
selectedStagePerformer: string | null; selectedStagePerformer: string | null;
selectedDealPerformer: string | null; selectedDealPerformer: string | null;
selectedStage: string | null; selectedStage: string | null;
utmFile: File | null;
questionEntity: TQuestionEntity; questionEntity: TQuestionEntity;
tags: TTags; tags: TTags;
}; };
@ -32,7 +30,6 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedStagePerformer, selectedStagePerformer,
selectedDealPerformer, selectedDealPerformer,
selectedStage, selectedStage,
utmFile,
questionEntity, questionEntity,
tags, tags,
}) => { }) => {
@ -68,17 +65,6 @@ export const SettingItem: FC<SettingItemProps> = ({
); );
} }
if (step === 4) { if (step === 4) {
return (
<Box sx={{ display: "flex", gap: "15px", marginTop: "20px" }}>
{utmFile ? (
<FileBlock file={utmFile} />
) : (
<Typography>Файл не загружен</Typography>
)}
</Box>
);
}
if (step === 5) {
const isFilled = Object.values(questionEntity).some( const isFilled = Object.values(questionEntity).some(
(array) => array.length > 0, (array) => array.length > 0,
); );
@ -110,7 +96,7 @@ export const SettingItem: FC<SettingItemProps> = ({
</> </>
); );
} }
if (step === 6) { if (step === 5) {
const isFilled = Object.values(tags).some((array) => array.length > 0); const isFilled = Object.values(tags).some((array) => array.length > 0);
const status = isFilled ? "Заполнено" : "Не заполнено"; const status = isFilled ? "Заполнено" : "Не заполнено";
@ -148,7 +134,6 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedStagePerformer, selectedStagePerformer,
selectedDealPerformer, selectedDealPerformer,
selectedStage, selectedStage,
utmFile,
questionEntity, questionEntity,
tags, tags,
]); ]);

@ -13,7 +13,6 @@ type SettingsBlockProps = {
selectedStagePerformer: string | null; selectedStagePerformer: string | null;
selectedStage: string | null; selectedStage: string | null;
selectedDealPerformer: string | null; selectedDealPerformer: string | null;
utmFile: File | null;
questionEntity: TQuestionEntity; questionEntity: TQuestionEntity;
tags: TTags; tags: TTags;
}; };
@ -27,7 +26,6 @@ export const SettingsBlock: FC<SettingsBlockProps> = ({
selectedStagePerformer, selectedStagePerformer,
selectedDealPerformer, selectedDealPerformer,
selectedStage, selectedStage,
utmFile,
questionEntity, questionEntity,
tags, tags,
}) => { }) => {
@ -68,7 +66,6 @@ export const SettingsBlock: FC<SettingsBlockProps> = ({
selectedStagePerformer={selectedStagePerformer} selectedStagePerformer={selectedStagePerformer}
selectedDealPerformer={selectedDealPerformer} selectedDealPerformer={selectedDealPerformer}
selectedStage={selectedStage} selectedStage={selectedStage}
utmFile={utmFile}
questionEntity={questionEntity} questionEntity={questionEntity}
tags={tags} tags={tags}
/> />

@ -25,11 +25,11 @@ interface Props {
companyName: keyof typeof QuizMetricType; companyName: keyof typeof QuizMetricType;
} }
export default function AnalyticsModal({ export const AnalyticsModal = ({
isModalOpen, isModalOpen,
handleCloseModal, handleCloseModal,
companyName, companyName,
}: Props) { }: Props) => {
const theme = useTheme(); const theme = useTheme();
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -260,4 +260,4 @@ export default function AnalyticsModal({
</Box> </Box>
</Dialog> </Dialog>
); );
} };

@ -1,12 +1,23 @@
import { Box, Typography, useTheme } from "@mui/material"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import React, { FC } from "react"; import React, { FC, lazy, Suspense } from "react";
import { ServiceButton } from "./ServiceButton/ServiceButton"; import { ServiceButton } from "./ServiceButton/ServiceButton";
import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo"; import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo";
import AnalyticsModal from "./AnalyticsModal/AnalyticsModal"; // import AnalyticsModal from "./AnalyticsModal/AnalyticsModal";
import { VKPixelLogo } from "../mocks/VKPixelLogo"; import { VKPixelLogo } from "../mocks/VKPixelLogo";
import { QuizMetricType } from "@model/quizSettings"; import { QuizMetricType } from "@model/quizSettings";
import { AmoCRMLogo } from "../mocks/AmoCRMLogo"; import { AmoCRMLogo } from "../mocks/AmoCRMLogo";
import { AmoCRMModal } from "../IntegrationsModal/AmoCRMModal";
const AnalyticsModal = lazy(() =>
import("./AnalyticsModal/AnalyticsModal").then((module) => ({
default: module.AnalyticsModal,
})),
);
const AmoCRMModal = lazy(() =>
import("../IntegrationsModal/AmoCRMModal").then((module) => ({
default: module.AmoCRMModal,
})),
);
type PartnersBoardProps = { type PartnersBoardProps = {
setIsModalOpen: (value: boolean) => void; setIsModalOpen: (value: boolean) => void;
@ -30,6 +41,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
handleCloseAmoSRMModal, handleCloseAmoSRMModal,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
return ( return (
<Box <Box
@ -99,18 +111,22 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
</Box> </Box>
</Box> </Box>
{companyName && ( {companyName && (
<AnalyticsModal <Suspense>
isModalOpen={isModalOpen} <AnalyticsModal
handleCloseModal={handleCloseModal} isModalOpen={isModalOpen}
companyName={companyName} handleCloseModal={handleCloseModal}
/> companyName={companyName}
/>
</Suspense>
)} )}
{companyName && ( {companyName && (
<AmoCRMModal <Suspense>
isModalOpen={isAmoCrmModalOpen} <AmoCRMModal
handleCloseModal={handleCloseAmoSRMModal} isModalOpen={isAmoCrmModalOpen}
companyName={companyName} handleCloseModal={handleCloseAmoSRMModal}
/> companyName={companyName}
/>
</Suspense>
)} )}
</Box> </Box>
); );

@ -11,7 +11,6 @@ import { DatePicker } from "@mui/x-date-pickers";
import moment from "moment"; import moment from "moment";
import type { Moment } from "moment"; import type { Moment } from "moment";
interface Props { interface Props {
label?: string; label?: string;
sx?: SxProps<Theme>; sx?: SxProps<Theme>;