Merge branch 'dev' into 'staging'

Dev

See merge request frontend/squiz!358
This commit is contained in:
Nastya 2024-07-23 10:57:59 +00:00
commit 69e49e8a81
46 changed files with 308 additions and 447 deletions

@ -20,7 +20,7 @@ import { Restore } from "./pages/auth/Restore";
import SigninDialog from "./pages/auth/Signin"; import SigninDialog from "./pages/auth/Signin";
import SignupDialog from "./pages/auth/Signup"; import SignupDialog from "./pages/auth/Signup";
import { InfoPrivilege } from "./pages/InfoPrivilege"; import { InfoPrivilege } from "./pages/InfoPrivilege";
import AmoTokenExpiredDialog from "./pages/IntegrationsPage/IntegrationsModal/AmoTokenExpiredDialog"; import AmoTokenExpiredDialog from "./pages/IntegrationsPage/IntegrationsModal/Amo/AmoTokenExpiredDialog";
import Landing from "./pages/Landing/Landing"; import Landing from "./pages/Landing/Landing";
import Main from "./pages/main"; import Main from "./pages/main";

@ -1,4 +1,4 @@
import { QuestionKeys } from "@/pages/IntegrationsPage/IntegrationsModal/types"; import { QuestionKeys } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
import { makeRequest } from "@api/makeRequest"; import { makeRequest } from "@api/makeRequest";
import { parseAxiosError } from "@utils/parse-error"; import { parseAxiosError } from "@utils/parse-error";
import useSWR from "swr"; import useSWR from "swr";

@ -105,7 +105,6 @@ export const getGraphics = async (
withCredentials: true, withCredentials: true,
}); });
console.log(questionsResponse)
return [questionsResponse]; return [questionsResponse];
} catch (nativeError) { } catch (nativeError) {
const [error] = parseAxiosError(nativeError); const [error] = parseAxiosError(nativeError);

@ -1,8 +1,8 @@
import * as React from "react"; import * as React from "react";
import { FC, useMemo } from "react"; import { FC, useMemo } from "react";
import CheckboxIcon from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
import { SelectChangeEvent, Typography, useTheme, Box, FormControlLabel, RadioGroup, Radio } from "@mui/material"; import { SelectChangeEvent, Typography, useTheme, Box, FormControlLabel, RadioGroup, Radio, useMediaQuery } from "@mui/material";
import { MinifiedData, TagKeys } from "@/pages/IntegrationsPage/IntegrationsModal/types"; import { MinifiedData, TagKeys } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
type CustomRadioGroupProps = { type CustomRadioGroupProps = {
items: MinifiedData[] | []; items: MinifiedData[] | [];
@ -20,22 +20,19 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
activeScope, activeScope,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const currentItem = useMemo(() => { const currentItem =
if (selectedItemId !== null && selectedItemId.length > 0) { (selectedItemId !== null && selectedItemId.length > 0) ?
return items.find((item) => item.id === selectedItemId) || null; items.find((item) => item.id === selectedItemId) || null
} :
return null; null;
}, [selectedItemId, items]);
const filteredItems = useMemo(() => { const filteredItems =
let newArray = items; (activeScope !== undefined) ?
if (activeScope !== undefined) items.filter((item) => {
newArray = newArray.filter((item) => {
return item.entity === activeScope; return item.entity === activeScope;
}); }) : items
return newArray;
}, items);
const onScroll = React.useCallback((e: React.UIEvent<HTMLDivElement>) => { const onScroll = React.useCallback((e: React.UIEvent<HTMLDivElement>) => {
const scrollHeight = e.currentTarget.scrollHeight; const scrollHeight = e.currentTarget.scrollHeight;
@ -48,9 +45,9 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
} }
}, []); }, []);
const formControlLabels = useMemo(() => { const formControlLabels =
if (filteredItems.length !== 0) { (filteredItems.length !== 0) ?
return filteredItems.map((item) => ( filteredItems.map((item) => (
<FormControlLabel <FormControlLabel
key={item.id} key={item.id}
sx={{ sx={{
@ -64,7 +61,7 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
backgroundColor: backgroundColor:
currentItem?.id === item.id ? theme.palette.background.default : theme.palette.common.white, currentItem?.id === item.id ? theme.palette.background.default : theme.palette.common.white,
"&.MuiFormControlLabel-root > .MuiTypography-root": { "&.MuiFormControlLabel-root > .MuiTypography-root": {
width: "200px", width: isMobile ? "150px" : "200px",
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap" whiteSpace: "nowrap"
@ -86,9 +83,9 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
label={item.title} label={item.title}
labelPlacement={"start"} labelPlacement={"start"}
/> />
)); ))
} :
return ( (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -100,8 +97,7 @@ export const CustomRadioGroup: FC<CustomRadioGroupProps> = ({
> >
<Typography>Нет элементов</Typography> <Typography>Нет элементов</Typography>
</Box> </Box>
); )
}, [filteredItems, selectedItemId]);
return ( return (
<Box <Box

@ -2,7 +2,7 @@ import * as React from "react";
import { FC, useCallback, useMemo, useRef, useState } from "react"; import { FC, useCallback, useMemo, useRef, useState } from "react";
import { Avatar, MenuItem, Select, SelectChangeEvent, Typography, useMediaQuery, useTheme, Box } from "@mui/material"; import { Avatar, MenuItem, Select, SelectChangeEvent, Typography, useMediaQuery, useTheme, Box } from "@mui/material";
import arrow_down from "../../assets/icons/arrow_down.svg"; import arrow_down from "../../assets/icons/arrow_down.svg";
import { MinifiedData } from "@/pages/IntegrationsPage/IntegrationsModal/types"; import { MinifiedData } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
type CustomSelectProps = { type CustomSelectProps = {
items: MinifiedData[] | []; items: MinifiedData[] | [];

@ -49,8 +49,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
const isTablet = useMediaQuery(theme.breakpoints.down(1000)); const isTablet = useMediaQuery(theme.breakpoints.down(1000));
const { questions } = useQuestions(); const { questions } = useQuestions();
console.log("КВЕШЕНЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫААААААААААААА")
console.log(questions)
const minifiedQuestions = useMemo( const minifiedQuestions = useMemo(
() => () =>
questions questions
@ -118,6 +116,7 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
questions, questions,
}); });
const handleAddTagQuestion = useCallback( const handleAddTagQuestion = useCallback(
(scope: QuestionKeys | TagKeys, id: string, type: "question" | "tag") => { (scope: QuestionKeys | TagKeys, id: string, type: "question" | "tag") => {
if (!scope || !id) return; if (!scope || !id) return;
@ -157,8 +156,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
} }
if (openDelete.type === "question") { if (openDelete.type === "question") {
console.log("delete id ", openDelete.id)
console.log("selectedQuestions ", selectedQuestions[openDelete.scope as QuestionKeys])
let newArray = selectedQuestions let newArray = selectedQuestions
newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(e => e.id !== openDelete.id) newArray[openDelete.scope as QuestionKeys] = newArray[openDelete.scope as QuestionKeys].filter(e => e.id !== openDelete.id)
// let index = -1 // let index = -1
@ -170,7 +167,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
// ...prevState, // ...prevState,
// [openDelete.scope]: newArray, // [openDelete.scope]: newArray,
// })); // }));
console.log("результат ебаный", newArray)
setSelectedQuestions(newArray); setSelectedQuestions(newArray);
setSelectedCurrentFields(selectedCurrentFields.filter(e => e.id !== openDelete.id)); setSelectedCurrentFields(selectedCurrentFields.filter(e => e.id !== openDelete.id));
@ -216,7 +212,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
selectedCurrentFields.forEach((data) => { selectedCurrentFields.forEach((data) => {
if (data.entity === "Contact") { if (data.entity === "Contact") {
console.log(data)
FieldsRule.Contact.ContactRuleMap[data.id] = Number(data.amoId) FieldsRule.Contact.ContactRuleMap[data.id] = Number(data.amoId)
} else { } else {
FieldsRule[data.entity].QuestionID[data.id] = Number(data.amoId) || 0 FieldsRule[data.entity].QuestionID[data.id] = Number(data.amoId) || 0
@ -229,8 +224,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
} }
body.FieldsRule = FieldsRule; body.FieldsRule = FieldsRule;
console.log(body)
if (firstRules) { if (firstRules) {
setIntegrationRules(quiz.backendId.toString(), body); setIntegrationRules(quiz.backendId.toString(), body);
} else { } else {
@ -338,6 +331,7 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
arrayOfPipelinesSteps, arrayOfPipelinesSteps,
arrayOfUsers, arrayOfUsers,
arrayOfTags, arrayOfTags,
arrayOfFields,
selectedPipeline, selectedPipeline,
selectedPipelineStep, selectedPipelineStep,
selectedDealUser, selectedDealUser,
@ -347,7 +341,6 @@ export const AmoCRMModal: FC<IntegrationsModalProps> = ({ isModalOpen, handleClo
arrayOfPipelinesSteps, arrayOfPipelinesSteps,
arrayOfUsers, arrayOfUsers,
minifiedQuestions, minifiedQuestions,
arrayOfTags,
selectedCurrentFields, selectedCurrentFields,
] ]
); );

@ -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,10 +1,11 @@
import { FC, useMemo, useState } from "react"; import { FC, useEffect, useMemo, useState } from "react";
import { ItemsSelectionView } from "./ItemsSelectionView/ItemsSelectionView"; import { ItemsSelectionView } from "./ItemsSelectionView/ItemsSelectionView";
import { ItemDetailsView } from "./ItemDetailsView/ItemDetailsView"; 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 "../AmoCRMModal";
import { DataConstrictor } from "../Components/DataConstrictor";
type Props = { type Props = {
selectedCurrentFields: MinifiedData[] | []; selectedCurrentFields: MinifiedData[] | [];
@ -41,10 +42,6 @@ export const AmoQuestions: FC<Props> = ({
FieldsAllowedFC, FieldsAllowedFC,
setSelectedCurrentFields setSelectedCurrentFields
}) => { }) => {
console.log("selectedCurrentFields")
console.log(selectedCurrentFields)
console.log("selectedQuestions")
console.log(selectedQuestions)
const [isSelection, setIsSelection] = useState<boolean>(false); const [isSelection, setIsSelection] = useState<boolean>(false);
const [activeScope, setActiveScope] = useState<QuestionKeys | null>(null); const [activeScope, setActiveScope] = useState<QuestionKeys | null>(null);
const [selectedQuestion, setSelectedQuestion] = useState<string | null>(null); const [selectedQuestion, setSelectedQuestion] = useState<string | null>(null);
@ -58,9 +55,9 @@ export const AmoQuestions: FC<Props> = ({
handleAddQuestion(activeScope, selectedQuestion, "question"); handleAddQuestion(activeScope, selectedQuestion, "question");
}; };
const handleAddCurrentField = () => { const handleAddCurrentField = () => {
if (activeScope === null || selectedField === null || selectedQuestion === null || if (activeScope === null || selectedField === null || selectedQuestion === null ||
selectedCurrentFields.some(e => (e.id === selectedQuestion) && e.entity === activeScope) selectedCurrentFields.some(e => (e.id === selectedQuestion) && e.entity === activeScope)
) return; ) return;
setActiveScope(null); setActiveScope(null);
//Убедимся что такой ФК не добавлялось //Убедимся что такой ФК не добавлялось
const newArray = selectedCurrentFields const newArray = selectedCurrentFields
@ -69,24 +66,19 @@ export const AmoQuestions: FC<Props> = ({
if (e.subTitle === selectedQuestion) index = i if (e.subTitle === selectedQuestion) index = i
}) })
if (index !== -1) newArray.splice(index, 1); if (index !== -1) newArray.splice(index, 1);
console.log(newArray)
newArray.push({ newArray.push({
id: selectedQuestion, id: selectedQuestion,
title: questionsItems.find(e => e.id === selectedQuestion)?.title || FCTranslate[selectedQuestion], title: questionsItems.find(e => e.id === selectedQuestion)?.title || FCTranslate[selectedQuestion],
entity: activeScope, entity: activeScope,
amoId: selectedField, amoId: selectedField,
}) })
console.log(newArray)
setSelectedCurrentFields(newArray); setSelectedCurrentFields(newArray);
}; };
const handleAdd = () => { const handleAdd = () => {
console.log(activeScope, selectedQuestion)
if (isCurrentFields) { if (isCurrentFields) {
console.log("добавляю текущее поле")
handleAddCurrentField() handleAddCurrentField()
} else { } else {
console.log("добавляю новое поле")
handleAddNewField() handleAddNewField()
} }
} }
@ -99,7 +91,7 @@ export const AmoQuestions: FC<Props> = ({
}); });
}; };
const SCFworld = (() => { const SCFworld = (() => {
const obj = { const obj = {
Lead: [], Lead: [],
Company: [], Company: [],
Customer: [], Customer: [],
@ -112,11 +104,36 @@ const obj = {
}) })
return obj return obj
})() })()
console.log("SCFworld")
console.log(SCFworld)
const [sortedFieldsAllowedFC, setSortedFieldsAllowedFC] = useState<MinifiedData[]>(FieldsAllowedFC);
const [sortedFieldsItems, setSortedFieldsItems] = useState<MinifiedData[]>(fieldsItems);
const [sortedquestionsItems, setSortedquestionsItems] = useState<MinifiedData[]>(questionsItems);
console.log("допущенные ФОРМА КОНТАКТОВ")
console.log(FieldsAllowedFC)
console.log("фильтрованные")
console.log(sortedFieldsAllowedFC)
console.log("")
console.log("допущенные вапросы")
console.log(questionsItems)
console.log("фильтрованные")
console.log(sortedquestionsItems)
const startConstrictor = (substr: string) => {
const a = FieldsAllowedFC.filter((mData) => mData.title.toLowerCase().startsWith(substr.toLowerCase()))
const b = fieldsItems.filter((mData) => mData.title.toLowerCase().startsWith(substr.toLowerCase()))
const c = questionsItems.filter((mData) => mData.title.toLowerCase().startsWith(substr.toLowerCase()))
setSortedFieldsAllowedFC(a);
setSortedFieldsItems(b);
setSortedquestionsItems(c);
}
useEffect(() => {
setSortedFieldsAllowedFC(FieldsAllowedFC);
setSortedFieldsItems(fieldsItems);
setSortedquestionsItems(questionsItems);
}, [activeScope])
return ( return (
<Box <Box
sx={{ sx={{
@ -127,28 +144,37 @@ const obj = {
}} }}
> >
{isSelection && activeScope !== null ? ( {isSelection && activeScope !== null ? (
<EntitiesQuestions <>
FieldsAllowedFC={FieldsAllowedFC} <DataConstrictor
fieldsItems={fieldsItems} isError={false}
items={diffArr(questionsItems, selectedQuestions[activeScope])} constrictor={startConstrictor}
selectedItemId={selectedQuestion} />
setSelectedQuestion={setSelectedQuestion}
selectedField={selectedField} {/* табличка */}
selectedCurrentFields={selectedCurrentFields}
setSelectedField={setSelectedField} <EntitiesQuestions
onSmallBtnClick={() => { FieldsAllowedFC={sortedFieldsAllowedFC}
setActiveScope(null); fieldsItems={sortedFieldsItems}
setIsSelection(false); items={(sortedquestionsItems.length === 0) ? [] : diffArr(sortedquestionsItems, selectedQuestions[activeScope])}
}} selectedItemId={selectedQuestion}
onLargeBtnClick={() => { setSelectedQuestion={setSelectedQuestion}
handleAdd(); selectedField={selectedField}
setActiveScope(null); selectedCurrentFields={selectedCurrentFields}
setIsSelection(false); setSelectedField={setSelectedField}
}} onSmallBtnClick={() => {
activeScope={activeScope} setActiveScope(null);
setIsCurrentFields={setIsCurrentFields} setIsSelection(false);
isCurrentFields={isCurrentFields} }}
/> onLargeBtnClick={() => {
handleAdd();
setActiveScope(null);
setIsSelection(false);
}}
activeScope={activeScope}
setIsCurrentFields={setIsCurrentFields}
isCurrentFields={isCurrentFields}
/>
</>
// Здесь выбираем элемент в табличку // Здесь выбираем элемент в табличку
// <ItemsSelectionView // <ItemsSelectionView
// items={questionsItems} // items={questionsItems}

@ -0,0 +1,97 @@
import * as React from "react";
import { FC, useCallback, useMemo, useRef, useState } from "react";
import { Avatar, MenuItem, Select, SelectChangeEvent, Typography, useMediaQuery, useTheme, Box } from "@mui/material";
import arrow_down from "@icons/arrow_down.svg";
import { MinifiedData } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
import { CustomRadioGroup } from "@/components/CustomRadioGroup/CustomRadioGroup";
type CustomSelectProps = {
items: MinifiedData[] | [];
selectedItemId: string | null;
setSelectedItem: (value: string | null) => void;
handleScroll: () => void;
};
export const CurrentFieldSelect: FC<CustomSelectProps> = ({ items, selectedItemId, setSelectedItem, handleScroll }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const ref = useRef<HTMLDivElement | null>(null);
const [opened, setOpened] = useState<boolean>(false);
const toggleOpened = useCallback(() => {
setOpened((isOpened) => !isOpened);
}, []);
const onScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
const scrollHeight = e.currentTarget.scrollHeight;
const scrollTop = e.currentTarget.scrollTop;
const clientHeight = e.currentTarget.clientHeight;
const scrolledToBottom = scrollTop / (scrollHeight - clientHeight) > 0.9;
if (scrolledToBottom) {
handleScroll();
}
}, []);
const currentItem = items.find((item) => item.id === selectedItemId) || null
return (
<Box>
<Box
sx={{
zIndex: 0,
position: "relative",
width: "100%",
height: "56px",
padding: "5px",
color: "#4D4D4D",
border: `2px solid ${theme.palette.common.white}`,
borderRadius: "12px",
background: "#EFF0F5",
display: "flex",
alignItems: "center",
cursor: "pointer",
}}
onClick={toggleOpened}
>
<Typography
sx={{
marginLeft: isMobile ? "10px" : "20px",
fontWeight: "400",
fontSize: "18px",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden",
flexGrow: 1,
}}
>
{currentItem?.title || "Выберите поле"}
</Typography>
<img
src={arrow_down}
alt="check"
style={{
position: "absolute",
top: "50%",
right: "10px",
transform: `translateY(-50%) rotate(${opened ? "180deg" : "0deg"}`,
height: "36px",
width: "36px",
}}
className={`select-icon ${opened ? "opened" : ""}`}
/>
</Box>
{opened &&
<CustomRadioGroup
items={items}
selectedItemId={selectedItemId}
setSelectedItem={setSelectedItem}
handleScroll={() => { }}
activeScope={undefined}
/>
}
</Box>
);
};

@ -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/AmoQuestions/CurrentFieldSelectMobile"; import {CurrentFieldSelect} from "@/pages/IntegrationsPage/IntegrationsModal/Amo/AmoQuestions/CurrentFieldSelectMobile";
interface Props { interface Props {
items: MinifiedData[]; items: MinifiedData[];

@ -41,6 +41,13 @@ export const EntitiesQuestions: FC<ItemsSelectionViewProps> = ({
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600)); const isMobile = useMediaQuery(theme.breakpoints.down(600));
console.log("--------------")
console.log("EntitiesQuestions")
console.log("вопросы")
console.log(items)
console.log("ФК")
console.log(FieldsAllowedFC)
console.log("------------------------------")
return ( return (
<Box <Box
@ -58,6 +65,7 @@ export const EntitiesQuestions: FC<ItemsSelectionViewProps> = ({
flexGrow: 1, flexGrow: 1,
width: "100%", width: "100%",
height: "346px", height: "346px",
overflow: "auto"
}} }}
> >
<Box> <Box>

@ -25,12 +25,7 @@ export const ItemDetailsView: FC<ItemDetailsViewProps> = ({
setActiveScope, setActiveScope,
deleteHC, deleteHC,
}) => { }) => {
console.log(selectedQuestions)
const theme = useTheme(); const theme = useTheme();
console.log("items")
console.log(items)
console.log("selectedQuestions")
console.log(selectedQuestions)
return ( return (
<Box <Box

@ -2,7 +2,7 @@ import { Box, IconButton, Typography, useTheme } from "@mui/material";
import { FC } from "react"; import { FC } from "react";
import { IconBtnAdd } from "./Item/IconBtnAdd/IconBtnAdd"; import { IconBtnAdd } from "./Item/IconBtnAdd/IconBtnAdd";
import { AnswerItem } from "./Item/AnswerItem/AnswerItem"; import { AnswerItem } from "./Item/AnswerItem/AnswerItem";
import { QuestionKeys, SelectedQuestions, TagKeys, SelectedTags, MinifiedData } from "../../types"; import { QuestionKeys, SelectedQuestions, TagKeys, SelectedTags, MinifiedData } from "../types";
type ItemProps = { type ItemProps = {
items: MinifiedData[]; items: MinifiedData[];

@ -1,5 +1,5 @@
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/StepButtonsBlock";
import { FC } from "react"; import { FC } from "react";
import { MinifiedData, TagKeys } from "../../types"; import { MinifiedData, TagKeys } from "../../types";

@ -3,6 +3,7 @@ import { Box } from "@mui/material";
import { ItemsSelectionView } from "../AmoQuestions/ItemsSelectionView/ItemsSelectionView"; import { ItemsSelectionView } from "../AmoQuestions/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";
type Props = { type Props = {
tagsItems: MinifiedData[] | []; tagsItems: MinifiedData[] | [];
@ -23,6 +24,8 @@ export const AmoTags: FC<Props> = ({
handlePrevStep, handlePrevStep,
handleNextStep, handleNextStep,
}) => { }) => {
const [sortedTagsItems, setSortedTagsItems] = useState<MinifiedData[] | []>(tagsItems);
const [isSelection, setIsSelection] = useState<boolean>(false); const [isSelection, setIsSelection] = useState<boolean>(false);
const [activeScope, setActiveScope] = useState<TagKeys | null>(null); const [activeScope, setActiveScope] = useState<TagKeys | null>(null);
const [selectedTag, setSelectedTag] = useState<string | null>(null); const [selectedTag, setSelectedTag] = useState<string | null>(null);
@ -39,6 +42,10 @@ export const AmoTags: FC<Props> = ({
type: "tag", type: "tag",
}); });
}; };
const startConstrictor = (substr: string) => {
const a = tagsItems.filter((mData) => mData.title.toLowerCase().startsWith(substr.toLowerCase()))
setSortedTagsItems(a);
}
return ( return (
<Box <Box
@ -51,22 +58,28 @@ export const AmoTags: FC<Props> = ({
> >
{isSelection && activeScope !== null ? ( {isSelection && activeScope !== null ? (
// Здесь выбираем элемент в табличку // Здесь выбираем элемент в табличку
<ItemsSelectionView <>
items={tagsItems} <DataConstrictor
selectedItemId={selectedTag} isError={sortedTagsItems.length === 0}
setSelectedItem={setSelectedTag} constrictor={startConstrictor}
handleScroll={handleScroll} />
activeScope={activeScope} <ItemsSelectionView
onSmallBtnClick={() => { items={sortedTagsItems}
setActiveScope(null); selectedItemId={selectedTag}
setIsSelection(false); setSelectedItem={setSelectedTag}
}} handleScroll={handleScroll}
onLargeBtnClick={() => { activeScope={activeScope}
handleAdd(); onSmallBtnClick={() => {
setActiveScope(null); setActiveScope(null);
setIsSelection(false); setIsSelection(false);
}} }}
/> onLargeBtnClick={() => {
handleAdd();
setActiveScope(null);
setIsSelection(false);
}}
/>
</>
) : ( ) : (
// Табличка // Табличка
<TagsDetailsView <TagsDetailsView

@ -1,4 +1,4 @@
import { Box, Typography, useTheme } from "@mui/material"; import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock"; import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
import { FC } from "react"; import { FC } from "react";
import { Item } from "../../AmoQuestions/Item/Item"; import { Item } from "../../AmoQuestions/Item/Item";
@ -25,6 +25,8 @@ export const TagsDetailsView: FC<TagsDetailsViewProps> = ({
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
return ( return (
<Box <Box
sx={{ sx={{
@ -45,13 +47,15 @@ export const TagsDetailsView: FC<TagsDetailsViewProps> = ({
padding: "10px", padding: "10px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)", boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
display: "flex", display: "flex",
flexDirection: isMobile ? "column" : "row",
}} }}
> >
<Box <Box
sx={{ sx={{
padding: "0 40px", p: isMobile ? "0" : "0 40px",
borderRight: `1px solid ${theme.palette.background.default}`, m: isMobile ? "5px auto 20px" : "0",
height: "100%", borderRight: isMobile ? "none" : `1px solid ${theme.palette.background.default}`,
height: isMobile ? "auto" : "100%",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
}} }}

@ -0,0 +1,62 @@
import { useState } from "react"
import { IconButton, Input, useMediaQuery, useTheme } from "@mui/material"
import Trash from "@/assets/icons/trash"
import { useDebouncedCallback } from "use-debounce"
interface Props {
isError: boolean
constrictor: (text: string) => void
}
export const DataConstrictor = ({
isError,
constrictor,
}: Props) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const [text, setText] = useState("")
const errCalc = isError && text.length > 0
const debouncedTestHC = useDebouncedCallback(
(value: string) => {
constrictor(value)
},
700
);
return <Input
value={text}
placeholder="быстрый поиск"
disableUnderline
sx={{
bgcolor: isError ? "#e6bbbb" : "#f2f3f7",
borderRadius: "10px",
maxWidth: isMobile ? "200px" : "300px",
p: "0 5px 0 15px",
mt: "10px",
"&:hover": {
bgcolor: errCalc ? "#e6bbbb" : "#ececec"
}
}}
endAdornment={
text.length > 0
?
<IconButton
onClick={() => {
setText("")
constrictor("")
}}
>
<Trash />
</IconButton>
:
null
}
onChange={({ target }) => {
setText(target.value)
debouncedTestHC(target.value)
}}
/>
}

@ -1,7 +1,7 @@
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/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 = {

@ -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/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 = {

@ -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/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 = {

@ -14,7 +14,7 @@ import {
} from "@/api/integration"; } from "@/api/integration";
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer"; import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
const SIZE = 175; const SIZE = 275;
interface Props { interface Props {
isModalOpen: boolean; isModalOpen: boolean;
@ -101,8 +101,6 @@ export const useAmoIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, que
if (gottenList !== null) { if (gottenList !== null) {
Object.keys(gottenList.QuestionID).forEach((qId) => { Object.keys(gottenList.QuestionID).forEach((qId) => {
console.log(qId)
console.log(questions)
const q = questions.find(e=>e.backendId === Number(qId)) || {} const q = questions.find(e=>e.backendId === Number(qId)) || {}
gottenQuestions[key as QuestionKeys].push({ gottenQuestions[key as QuestionKeys].push({
id: qId, id: qId,
@ -126,7 +124,6 @@ export const useAmoIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, que
amoId: MAP[key].toString(), amoId: MAP[key].toString(),
}) })
} }
console.log(list)
setSelectedCurrentFields(list) setSelectedCurrentFields(list)
} }
} }

@ -1,189 +0,0 @@
import * as React from "react";
import { FC, useCallback, useMemo, useRef, useState } from "react";
import { Avatar, MenuItem, Select, SelectChangeEvent, Typography, useMediaQuery, useTheme, Box } from "@mui/material";
import arrow_down from "@icons/arrow_down.svg";
import { MinifiedData } from "@/pages/IntegrationsPage/IntegrationsModal/types";
type CustomSelectProps = {
items: MinifiedData[] | [];
selectedItemId: string | null;
setSelectedItem: (value: string | null) => void;
handleScroll: () => void;
};
export const CurrentFieldSelect: FC<CustomSelectProps> = ({ items, selectedItemId, setSelectedItem, handleScroll }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const ref = useRef<HTMLDivElement | null>(null);
const [opened, setOpened] = useState<boolean>(false);
const toggleOpened = useCallback(() => {
setOpened((isOpened) => !isOpened);
}, []);
const onScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
const scrollHeight = e.currentTarget.scrollHeight;
const scrollTop = e.currentTarget.scrollTop;
const clientHeight = e.currentTarget.clientHeight;
const scrolledToBottom = scrollTop / (scrollHeight - clientHeight) > 0.9;
if (scrolledToBottom) {
handleScroll();
}
}, []);
const currentItem = useMemo(() => items.find((item) => item.id === selectedItemId) || null, [selectedItemId, items]);
const menuItems = useMemo(() => {
if (items.length !== 0) {
return items.map((item) => (
<MenuItem
key={item.id}
value={item.id}
sx={{
padding: "6px 0",
zIndex: 5,
borderTop: "1px solid rgba(154, 154, 175, 0.1)",
width: "auto",
}}
>
<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",
}}
>
{item.title}
</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",
}}
>
{item.subTitle}
</Typography>
</Box>
</MenuItem>
));
}
return (
<MenuItem
key={"-1"}
disabled
sx={{ padding: "12px", zIndex: 2 }}
>
нет данных
</MenuItem>
);
}, [items, selectedItemId]);
return (
<Box>
<Box
sx={{
zIndex: 0,
position: "relative",
width: "100%",
height: "56px",
padding: "5px",
color: "#4D4D4D",
border: `2px solid ${theme.palette.common.white}`,
borderRadius: "12px",
background: "#EFF0F5",
display: "flex",
alignItems: "center",
cursor: "pointer",
}}
onClick={() => {
if (ref.current !== null) ref.current?.click();
}}
>
<Typography
sx={{
marginLeft: isMobile ? "10px" : "20px",
fontWeight: "400" ,
fontSize: "18px",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden",
flexGrow: 1,
}}
>
{currentItem?.title || "Выберите поле"}
</Typography>
<img
src={arrow_down}
alt="check"
style={{
position: "absolute",
top: "50%",
right: "10px",
transform: `translateY(-50%) rotate(${opened ? "180deg" : "0deg"}`,
height: "36px",
width: "36px",
}}
className={`select-icon ${opened ? "opened" : ""}`}
/>
</Box>
<Select
ref={ref}
className="select"
value={selectedItemId || ""}
open={opened}
MenuProps={{
disablePortal: true,
PaperProps: {
onScroll: onScroll,
style: {
zIndex: 2,
minWidth: undefined,
maxHeight: "300px",
overflow: "auto",
overflowX: "auto",
paddingTop: 0,
marginTop: "-50px",
borderRadius: "12px",
border: "1px solid",
maxWidth: "calc(100% - 104px)",
left: "52px",
boxShadow: "none"
},
},
}}
sx={{
display: "block",
"& .MuiSelect-select.MuiSelect-outlined.MuiInputBase-input": {
display: "none",
},
"& .MuiSelect-icon": {
display: "none",
},
"& .MuiOutlinedInput-notchedOutline": {
border: 0,
},
}}
onChange={({ target }: SelectChangeEvent<string>) => setSelectedItem(target.value)}
onClick={toggleOpened}
>
{menuItems}
</Select>
</Box>
);
};

@ -16,7 +16,7 @@ const AnalyticsModal = lazy(() =>
); );
const AmoCRMModal = lazy(() => const AmoCRMModal = lazy(() =>
import("../IntegrationsModal/AmoCRMModal").then((module) => ({ import("../IntegrationsModal/Amo/AmoCRMModal").then((module) => ({
default: module.AmoCRMModal, default: module.AmoCRMModal,
})) }))
); );
@ -60,7 +60,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
> >
<Box> <Box>
{ {
user.user._id === "6694dc24d5802e9f13662a7e" && user.user._id === "6692e068983ee77f8e1e682e" &&
<> <>
<Typography <Typography
variant="h6" variant="h6"

@ -297,8 +297,6 @@ export const CardAnswer: FC<CardAnswerProps> = ({
}} }}
> >
{resultsAnswer.map((answer, id) => { {resultsAnswer.map((answer, id) => {
// console.log(answer)
// console.log(answer.content)
let titleQuestion; let titleQuestion;
let typeOuestion; let typeOuestion;
let typeQuestionFile; let typeQuestionFile;
@ -308,7 +306,6 @@ export const CardAnswer: FC<CardAnswerProps> = ({
let idAnswer = answer.question_id; //айди вопроса у ответа let idAnswer = answer.question_id; //айди вопроса у ответа
for (i in quest) { for (i in quest) {
if (quest[i].backendId === idAnswer) { if (quest[i].backendId === idAnswer) {
console.log(quest[i])
titleQuestion = quest[i].title; titleQuestion = quest[i].title;
typeOuestion = quest[i].type; typeOuestion = quest[i].type;
typeQuestionFile = quest[i].content.type; typeQuestionFile = quest[i].content.type;

@ -135,18 +135,14 @@ function TariffPage() {
//Если нам хватает денежек - покупаем тариф //Если нам хватает денежек - покупаем тариф
const [data, payError] = await cartApi.pay(); const [data, payError] = await cartApi.pay();
console.log(payError)
if (payError || !data) { if (payError || !data) {
//если денег не хватило //если денег не хватило
if (payError?.includes("insufficient funds") || payError?.includes("Payment Required")) { if (payError?.includes("insufficient funds") || payError?.includes("Payment Required")) {
let cashDif = Number(payError.split(":")[1]); let cashDif = Number(payError.split(":")[1]);
console.log(payError)
console.log(cashDif)
var link = document.createElement("a"); var link = document.createElement("a");
link.href = `https://${isTestServer ? "s" : ""}hub.pena.digital/quizpayment?action=squizpay&dif=${cashDif}&data=${token}&userid=${userId}`; link.href = `https://${isTestServer ? "s" : ""}hub.pena.digital/quizpayment?action=squizpay&dif=${cashDif}&data=${token}&userid=${userId}`;
document.body.appendChild(link); document.body.appendChild(link);
console.log(link)
link.click(); link.click();
return; return;
} }
@ -440,11 +436,7 @@ const outCart = (cart: string[]) => {
} }
let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]") || []; let saveCart = JSON.parse(localStorage.getItem("saveCart") || "[]") || [];
console.log("saveCart")
console.log(saveCart)
if (!Array.isArray(saveCart)) saveCart = [] if (!Array.isArray(saveCart)) saveCart = []
console.log("saveCart")
console.log(saveCart)
saveCart = saveCart.push(id); saveCart = saveCart.push(id);
localStorage.setItem("saveCart", JSON.stringify(saveCart)); localStorage.setItem("saveCart", JSON.stringify(saveCart));
}); });

@ -9,7 +9,6 @@ export default function CreateButtons({ mt }: string) {
const navigate = useNavigate(); const navigate = useNavigate();
const theme = useTheme(); const theme = useTheme();
const user = useUserStore(); const user = useUserStore();
console.log(user)
const isMobile = useMediaQuery(theme.breakpoints.down(500)); const isMobile = useMediaQuery(theme.breakpoints.down(500));
return ( return (
@ -22,7 +21,7 @@ export default function CreateButtons({ mt }: string) {
}} }}
> >
{ {
user.user._id === "6694dc24d5802e9f13662a7e" && user.user._id === "6692e068983ee77f8e1e682e" &&
<Link to="/gallery" style={{ textDecoration: "none" }}> <Link to="/gallery" style={{ textDecoration: "none" }}>
<Button <Button
sx={{ sx={{

@ -21,7 +21,7 @@ import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate"; import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate";
import { ConfirmLeaveModal } from "./ConfirmLeaveModal"; import { ConfirmLeaveModal } from "./ConfirmLeaveModal";
import { checkQuestionHint } from "@utils/checkQuestionHint"; import { checkQuestionHint } from "@utils/checkQuestionHint";
import AmoTokenExpiredDialog from "../IntegrationsPage/IntegrationsModal/AmoTokenExpiredDialog"; import AmoTokenExpiredDialog from "../IntegrationsPage/IntegrationsModal/Amo/AmoTokenExpiredDialog";
import { useAmoAccount } from "@/api/integration"; import { useAmoAccount } from "@/api/integration";
interface Props { interface Props {

@ -1,51 +0,0 @@
import { Avatar, Box, SxProps, Theme, Typography } from "@mui/material";
interface Props {
sx: SxProps<Theme>;
}
export default function CustomAvatar({ sx }: Props) {
return (
<Avatar sx={sx}>
<Typography
sx={{
fontWeight: 500,
fontSize: "14px",
lineHeight: "20px",
zIndex: 1,
}}
>
AA
</Typography>
<Box sx={{ position: "absolute" }}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="37"
height="36"
viewBox="0 0 37 36"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16.0896 15.3939C16.1897 9.41281 22.9128 5.35966 28.711 3.9153C34.7649 2.40721 41.974 3.19598 46.0209 7.93784C49.6931 12.2405 46.8503 18.5029 45.9355 24.0976C45.2565 28.2502 44.7264 32.5083 41.552 35.2692C38.1345 38.2416 32.8105 41.3312 29.1224 38.7209C25.459 36.1281 30.5336 29.8417 28.3428 25.9204C25.5777 20.9711 15.9947 21.0705 16.0896 15.3939Z"
fill="#FC712F"
/>
<circle
cx="28.7954"
cy="-4.08489"
r="5.51855"
transform="rotate(-32.339 28.7954 -4.08489)"
fill="#FC712F"
/>
<circle
cx="25.1065"
cy="28.2781"
r="1.26958"
transform="rotate(-32.339 25.1065 28.2781)"
fill="#FC712F"
/>
</svg>
</Box>
</Avatar>
);
}

@ -1,32 +0,0 @@
import { Link, Typography, useTheme } from "@mui/material";
interface Props {
text: string;
isActive?: boolean;
onClick?: () => void;
href?: string;
}
export default function NavMenuItem({
href,
onClick,
text,
isActive = false,
}: Props) {
const theme = useTheme();
return (
<Link href={href} underline="none" onClick={onClick}>
я есть навбар меню итем
<Typography
color={isActive ? theme.palette.brightPurple.main : undefined}
variant="body2"
sx={{
whiteSpace: "nowrap",
}}
>
{text}
</Typography>
</Link>
);
}

@ -1,45 +0,0 @@
import { IconButton, useTheme } from "@mui/material";
import SectionWrapper from "../SectionWrapper";
import MenuIcon from "@mui/icons-material/Menu";
import PenaLogo from "@ui_kit/PenaLogo";
interface Props {
isLoggedIn: boolean;
}
export default function NavbarCollapsed({ isLoggedIn }: Props) {
const theme = useTheme();
return (
<SectionWrapper
component="nav"
maxWidth="lg"
outerContainerSx={{
backgroundColor: theme.palette.navbarbg.main,
position: "sticky",
top: 0,
zIndex: 1,
}}
sx={{
height: "51px",
py: "6px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
я подписан как навбар коллапсед
<PenaLogo width={100} />
<IconButton
sx={{
p: 0,
height: "30px",
width: "30px",
color: theme.palette.primary.main,
}}
>
<MenuIcon sx={{ height: "30px", width: "30px" }} />
</IconButton>
</SectionWrapper>
);
}