Merge branch 'add-vk-into-integrations' into 'dev'
Add vk into integrations See merge request frontend/squiz!294
This commit is contained in:
commit
246a090d10
@ -118,6 +118,11 @@ export interface QuizConfig {
|
|||||||
vkMetricNumber: number | undefined;
|
vkMetricNumber: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum QuizMetricType {
|
||||||
|
yandex = "yandexMetricNumber",
|
||||||
|
vk = "vkMetricNumber",
|
||||||
|
}
|
||||||
|
|
||||||
export type FormContactFieldName =
|
export type FormContactFieldName =
|
||||||
| "name"
|
| "name"
|
||||||
| "email"
|
| "email"
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
import { Box, useTheme } from "@mui/material";
|
|
||||||
import { FC } from "react";
|
|
||||||
import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo";
|
|
||||||
|
|
||||||
type PartnerItemProps = {
|
|
||||||
setIsModalOpen: (value: boolean) => void;
|
|
||||||
setCompanyName?: (value: string) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const YandexButton: FC<PartnerItemProps> = ({
|
|
||||||
setIsModalOpen,
|
|
||||||
setCompanyName,
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
setIsModalOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: 250,
|
|
||||||
height: 60,
|
|
||||||
backgroundColor: "white",
|
|
||||||
borderRadius: "8px",
|
|
||||||
padding: "0 20px",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
marginBottom: "2%",
|
|
||||||
marginRight: "2%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={() => setIsModalOpen(true)}
|
|
||||||
>
|
|
||||||
<YandexMetricaLogo />
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,197 +0,0 @@
|
|||||||
import {
|
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
IconButton,
|
|
||||||
Typography,
|
|
||||||
useMediaQuery,
|
|
||||||
useTheme,
|
|
||||||
} from "@mui/material";
|
|
||||||
import Box from "@mui/material/Box";
|
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import CustomTextField from "@ui_kit/CustomTextField";
|
|
||||||
import EditPencil from "@icons/EditPencil";
|
|
||||||
import Trash from "@icons/trash";
|
|
||||||
import { updateQuiz } from "@root/quizes/actions";
|
|
||||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
isModalOpen: boolean;
|
|
||||||
handleCloseModal: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function YandexModal({ isModalOpen, handleCloseModal }: Props) {
|
|
||||||
const theme = useTheme();
|
|
||||||
const quiz = useCurrentQuiz();
|
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
|
||||||
const yandexNumber = quiz?.config.yandexMetricNumber;
|
|
||||||
const [isSave, setIsSave] = useState<boolean>(!!yandexNumber);
|
|
||||||
const [currentValue, setCurrentValue] = useState<string>(
|
|
||||||
yandexNumber ? yandexNumber.toString() : "",
|
|
||||||
);
|
|
||||||
const handleClose = () => {
|
|
||||||
handleCloseModal();
|
|
||||||
if (!yandexNumber) {
|
|
||||||
setIsSave(false);
|
|
||||||
setCurrentValue("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsSave(true);
|
|
||||||
setCurrentValue(yandexNumber.toString());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave = () => {
|
|
||||||
handleCloseModal();
|
|
||||||
updateQuiz(quiz?.id, (quiz) => {
|
|
||||||
quiz.config.yandexMetricNumber = currentValue
|
|
||||||
? Number(currentValue)
|
|
||||||
: undefined;
|
|
||||||
});
|
|
||||||
if (!currentValue) {
|
|
||||||
setIsSave(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsSave(true);
|
|
||||||
};
|
|
||||||
const handleEdit = () => {
|
|
||||||
setIsSave(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClear = () => {
|
|
||||||
setCurrentValue("");
|
|
||||||
setIsSave(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog
|
|
||||||
open={isModalOpen}
|
|
||||||
onClose={handleClose}
|
|
||||||
fullWidth
|
|
||||||
PaperProps={{
|
|
||||||
sx: {
|
|
||||||
maxWidth: isTablet ? "100%" : "580px",
|
|
||||||
maxHeight: isTablet ? "100%" : "251px",
|
|
||||||
borderRadius: "12px",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
height: "68px",
|
|
||||||
backgroundColor: theme.palette.background.default,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: isMobile ? "20px" : "24px",
|
|
||||||
fontWeight: "500",
|
|
||||||
padding: "20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Аналитика с Яндекс.Метрикой
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<IconButton
|
|
||||||
onClick={handleClose}
|
|
||||||
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",
|
|
||||||
padding: "15px 20px 15px",
|
|
||||||
flexGrow: 1,
|
|
||||||
gap: "20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography fontWeight={500}>
|
|
||||||
{isSave ? "Ваш номер счетчика" : "Введите номер счетчика"}
|
|
||||||
</Typography>
|
|
||||||
{isSave && (
|
|
||||||
<Box>
|
|
||||||
<IconButton onClick={handleEdit}>
|
|
||||||
<EditPencil
|
|
||||||
color={theme.palette.brightPurple.main}
|
|
||||||
width={"18px"}
|
|
||||||
height={"18px"}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
<IconButton onClick={handleClear}>
|
|
||||||
<Trash
|
|
||||||
sx={{
|
|
||||||
width: "24px",
|
|
||||||
"& path": {
|
|
||||||
stroke: theme.palette.brightPurple.main,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<CustomTextField
|
|
||||||
placeholder={isSave ? currentValue : "в формате ХХХХХХХХ"}
|
|
||||||
type={"number"}
|
|
||||||
value={currentValue}
|
|
||||||
disabled={isSave}
|
|
||||||
onChange={(e) => {
|
|
||||||
const onlyNums = e.target.value.replace(/[^0-9]/g, "");
|
|
||||||
setCurrentValue(onlyNums);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
{!isSave && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: isMobile ? "space-between" : "end",
|
|
||||||
gap: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
sx={{ width: isMobile ? "100%" : "130px" }}
|
|
||||||
onClick={handleClose}
|
|
||||||
variant={"outlined"}
|
|
||||||
>
|
|
||||||
Отмена
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
sx={{ width: isMobile ? "100%" : "130px" }}
|
|
||||||
variant={"contained"}
|
|
||||||
onClick={handleSave}
|
|
||||||
>
|
|
||||||
Сохранить
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -6,6 +6,7 @@ import { useQuizStore } from "@root/quizes/store";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { PartnersBoard } from "./PartnersBoard/PartnersBoard";
|
import { PartnersBoard } from "./PartnersBoard/PartnersBoard";
|
||||||
import { partnersMock } from "./mocks/MockData";
|
import { partnersMock } from "./mocks/MockData";
|
||||||
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
|
|
||||||
interface IntegrationsPageProps {
|
interface IntegrationsPageProps {
|
||||||
heightSidebar: number;
|
heightSidebar: number;
|
||||||
@ -22,7 +23,9 @@ export const IntegrationsPage = ({
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
||||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||||
const [companyName, setCompanyName] = useState<string | null>(null);
|
const [companyName, setCompanyName] = useState<
|
||||||
|
keyof typeof QuizMetricType | null
|
||||||
|
>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editQuizId === null) navigate("/list");
|
if (editQuizId === null) navigate("/list");
|
||||||
}, [navigate, editQuizId]);
|
}, [navigate, editQuizId]);
|
||||||
@ -62,6 +65,7 @@ export const IntegrationsPage = ({
|
|||||||
<PartnersBoard
|
<PartnersBoard
|
||||||
partners={partnersMock}
|
partners={partnersMock}
|
||||||
setIsModalOpen={setIsModalOpen}
|
setIsModalOpen={setIsModalOpen}
|
||||||
|
companyName={companyName}
|
||||||
setCompanyName={setCompanyName}
|
setCompanyName={setCompanyName}
|
||||||
isModalOpen={isModalOpen}
|
isModalOpen={isModalOpen}
|
||||||
handleCloseModal={handleCloseModal}
|
handleCloseModal={handleCloseModal}
|
||||||
|
|||||||
@ -0,0 +1,263 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
IconButton,
|
||||||
|
Typography,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
|
import CustomTextField from "@ui_kit/CustomTextField";
|
||||||
|
import EditPencil from "@icons/EditPencil";
|
||||||
|
import Trash from "@icons/trash";
|
||||||
|
import { updateQuiz } from "@root/quizes/actions";
|
||||||
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||||
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
|
import { InstructionsBlock } from "./IntsructionsBlock/InstructionsBlock";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isModalOpen: boolean;
|
||||||
|
handleCloseModal: () => void;
|
||||||
|
companyName: keyof typeof QuizMetricType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AnalyticsModal({
|
||||||
|
isModalOpen,
|
||||||
|
handleCloseModal,
|
||||||
|
companyName,
|
||||||
|
}: Props) {
|
||||||
|
const theme = useTheme();
|
||||||
|
const quiz = useCurrentQuiz();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||||
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
|
const configName = QuizMetricType[companyName];
|
||||||
|
const meterNumber = quiz?.config[configName];
|
||||||
|
const [isSave, setIsSave] = useState<boolean>(!!meterNumber);
|
||||||
|
const [currentValue, setCurrentValue] = useState<string>(
|
||||||
|
meterNumber ? meterNumber.toString() : "",
|
||||||
|
);
|
||||||
|
const analyticTexts = useMemo(() => {
|
||||||
|
return {
|
||||||
|
yandex: {
|
||||||
|
header: "Яндекс.Метрикой",
|
||||||
|
counterName: "счетчика",
|
||||||
|
instructionTitle: "Как установить Яндекс Метрику в квиз?",
|
||||||
|
instructionSubTitle: "Инструкция по настройке Яндекс Метрики",
|
||||||
|
instructionHeader: "Настройка счётчика и интеграции",
|
||||||
|
instructionText:
|
||||||
|
"Повседневная практика показывает, что дальнейшее развитие различных форм деятельности требуют определения и уточнения соответствующий условий активизации.Повседневная практика показывает, что дальнейшее развитие различных форм деятельности требуют определения и уточнения соответствующий условий активизации.Повседневная практика показывает, что дальнейшее развитие различных форм деятельности требуют определения и уточнения соответствующий условий активизации.",
|
||||||
|
},
|
||||||
|
vk: {
|
||||||
|
header: "VK Пиксель",
|
||||||
|
counterName: "пикселя",
|
||||||
|
instructionTitle: "Как установить VK Пиксель в квиз?",
|
||||||
|
instructionSubTitle: "Инструкция по настройке VK Пиксель",
|
||||||
|
instructionHeader: "Настройка счётчика и интеграции",
|
||||||
|
instructionText:
|
||||||
|
"Повседневная практика показывает, что дальнейшее развитие различных форм деятельности требуют определения и уточнения соответствующий условий активизации.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
handleCloseModal();
|
||||||
|
if (!meterNumber) {
|
||||||
|
setIsSave(false);
|
||||||
|
setCurrentValue("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsSave(true);
|
||||||
|
setCurrentValue(meterNumber.toString());
|
||||||
|
};
|
||||||
|
const handleSave = () => {
|
||||||
|
handleCloseModal();
|
||||||
|
updateQuiz(quiz?.id, (quiz) => {
|
||||||
|
quiz.config[configName] = currentValue ? Number(currentValue) : undefined;
|
||||||
|
});
|
||||||
|
if (!currentValue) {
|
||||||
|
setIsSave(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsSave(true);
|
||||||
|
};
|
||||||
|
const handleEdit = () => {
|
||||||
|
setIsSave(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setCurrentValue("");
|
||||||
|
setIsSave(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const configName =
|
||||||
|
QuizMetricType[companyName as keyof typeof QuizMetricType];
|
||||||
|
const meterNumber = quiz?.config[configName];
|
||||||
|
setCurrentValue(meterNumber ? meterNumber.toString() : "");
|
||||||
|
setIsSave(!!meterNumber);
|
||||||
|
}, [companyName]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={isModalOpen}
|
||||||
|
onClose={handleClose}
|
||||||
|
fullWidth
|
||||||
|
PaperProps={{
|
||||||
|
sx: {
|
||||||
|
maxWidth: isTablet ? "100%" : "920px",
|
||||||
|
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,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Аналитика с {analyticTexts[companyName]?.header}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleClose}
|
||||||
|
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",
|
||||||
|
padding: "20px 20px",
|
||||||
|
flexGrow: 1,
|
||||||
|
gap: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
maxWidth: isMobile ? "100%" : "590px",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography fontWeight={500}>
|
||||||
|
{isSave
|
||||||
|
? `Ваш номер ${analyticTexts[companyName]?.counterName}`
|
||||||
|
: `Введите номер ${analyticTexts[companyName]?.counterName}`}
|
||||||
|
</Typography>
|
||||||
|
{isSave && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
position: "absolute",
|
||||||
|
right: "0",
|
||||||
|
top: "0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton onClick={handleEdit} sx={{ padding: "0" }}>
|
||||||
|
<EditPencil
|
||||||
|
color={theme.palette.brightPurple.main}
|
||||||
|
width={"24px"}
|
||||||
|
height={"24px"}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={handleClear} sx={{ padding: "0" }}>
|
||||||
|
<Trash
|
||||||
|
sx={{
|
||||||
|
width: "24px",
|
||||||
|
"& path": {
|
||||||
|
stroke: theme.palette.brightPurple.main,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: isMobile ? "column" : "row",
|
||||||
|
gap: "20px",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomTextField
|
||||||
|
sxForm={{ maxWidth: isMobile ? "100%" : "590px" }}
|
||||||
|
placeholder={isSave ? currentValue : "в формате ХХХХХХХХ"}
|
||||||
|
type={"number"}
|
||||||
|
value={currentValue}
|
||||||
|
disabled={isSave}
|
||||||
|
onChange={(e) => {
|
||||||
|
const onlyNums = e.target.value.replace(/[^0-9]/g, "");
|
||||||
|
setCurrentValue(onlyNums);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!isSave && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: isMobile ? "100%" : "auto",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: isMobile ? "space-between" : "end",
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{meterNumber && !isSave && (
|
||||||
|
<Button
|
||||||
|
sx={{ width: isMobile ? "100%" : "130px", height: "44px" }}
|
||||||
|
onClick={handleClose}
|
||||||
|
variant={"outlined"}
|
||||||
|
>
|
||||||
|
Отмена
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
sx={{ width: isMobile ? "100%" : "130px", height: "44px" }}
|
||||||
|
variant={"contained"}
|
||||||
|
onClick={handleSave}
|
||||||
|
>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<InstructionsBlock
|
||||||
|
headerText={analyticTexts[companyName]?.instructionTitle}
|
||||||
|
subHeaderText={analyticTexts[companyName]?.instructionSubTitle}
|
||||||
|
instructionTitle={analyticTexts[companyName]?.instructionHeader}
|
||||||
|
instructionsText={analyticTexts[companyName]?.instructionText}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
88
src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/InstructionsBlock.tsx
Normal file
88
src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/InstructionsBlock.tsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
||||||
|
import { Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
|
import React, { FC, useState } from "react";
|
||||||
|
|
||||||
|
type InstructionsBlockProps = {
|
||||||
|
headerText: string;
|
||||||
|
subHeaderText: string;
|
||||||
|
instructionTitle: string;
|
||||||
|
instructionsText: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InstructionsBlock: FC<InstructionsBlockProps> = ({
|
||||||
|
headerText,
|
||||||
|
instructionsText,
|
||||||
|
subHeaderText,
|
||||||
|
instructionTitle,
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down(600));
|
||||||
|
const [isInstructionOpen, setIsInstructionOpen] = useState(false);
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Box
|
||||||
|
onClick={() => setIsInstructionOpen(!isInstructionOpen)}
|
||||||
|
sx={{
|
||||||
|
cursor: "pointer",
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
borderRadius: isInstructionOpen ? "12px 12px 0 0" : "12px",
|
||||||
|
padding: "20px",
|
||||||
|
border: "1px solid #E5E5E5",
|
||||||
|
borderBottom: isInstructionOpen ? "none" : "1px solid #E5E5E5",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isMobile && (
|
||||||
|
<KeyboardArrowUpIcon
|
||||||
|
fontSize="medium"
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "20px",
|
||||||
|
right: "20px",
|
||||||
|
transition: "transform 0.3s",
|
||||||
|
transform: isInstructionOpen ? "rotate(0deg" : "rotate(180deg)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
marginBottom: "4px",
|
||||||
|
fontWeight: "500",
|
||||||
|
width: isMobile ? "90%" : "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{headerText}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ fontSize: "16px", color: theme.palette.grey2.main }}>
|
||||||
|
{subHeaderText}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
{isInstructionOpen && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
borderRadius: " 0 0 12px 12px",
|
||||||
|
padding: "20px",
|
||||||
|
border: "1px solid #E5E5E5",
|
||||||
|
borderTop: isInstructionOpen ? "none" : "1px solid #E5E5E5",
|
||||||
|
maxHeight: isMobile ? "240px" : "300px",
|
||||||
|
overflowY: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: "500",
|
||||||
|
color: theme.palette.grey3.main,
|
||||||
|
marginBottom: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{instructionTitle}
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ color: theme.palette.grey3.main }}>
|
||||||
|
{instructionsText}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import { Box, Typography, useTheme } from "@mui/material";
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { YandexButton } from "../IntegrationYandex/YandexButton";
|
import { ServiceButton } from "./ServiceButton/ServiceButton";
|
||||||
import YandexModal from "../IntegrationYandex/YandexModal";
|
import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo";
|
||||||
|
import AnalyticsModal from "./AnalyticsModal/AnalyticsModal";
|
||||||
|
import { VKPixelLogo } from "../mocks/VKPixelLogo";
|
||||||
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
|
|
||||||
export type Partner = {
|
export type Partner = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -12,7 +15,8 @@ export type Partner = {
|
|||||||
type PartnersBoardProps = {
|
type PartnersBoardProps = {
|
||||||
partners: Partner[];
|
partners: Partner[];
|
||||||
setIsModalOpen: (value: boolean) => void;
|
setIsModalOpen: (value: boolean) => void;
|
||||||
setCompanyName: (value: string) => void;
|
companyName: keyof typeof QuizMetricType | null;
|
||||||
|
setCompanyName: (value: keyof typeof QuizMetricType) => void;
|
||||||
isModalOpen: boolean;
|
isModalOpen: boolean;
|
||||||
handleCloseModal: () => void;
|
handleCloseModal: () => void;
|
||||||
};
|
};
|
||||||
@ -22,17 +26,18 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
|
|||||||
setIsModalOpen,
|
setIsModalOpen,
|
||||||
isModalOpen,
|
isModalOpen,
|
||||||
handleCloseModal,
|
handleCloseModal,
|
||||||
|
companyName,
|
||||||
setCompanyName,
|
setCompanyName,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const partnersByCategory = partners.reduce(
|
// const partnersByCategory = partners.reduce(
|
||||||
(acc, partner) => {
|
// (acc, partner) => {
|
||||||
(acc[partner.category] = acc[partner.category] || []).push(partner);
|
// (acc[partner.category] = acc[partner.category] || []).push(partner);
|
||||||
return acc;
|
// return acc;
|
||||||
},
|
// },
|
||||||
{} as Record<string, Partner[]>,
|
// {} as Record<string, Partner[]>,
|
||||||
);
|
// );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -74,21 +79,47 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
|
|||||||
{/* </Box>*/}
|
{/* </Box>*/}
|
||||||
{/* </Box>*/}
|
{/* </Box>*/}
|
||||||
{/*))}*/}
|
{/*))}*/}
|
||||||
<Typography
|
|
||||||
variant="h6"
|
<Box>
|
||||||
sx={{
|
<Typography
|
||||||
textAlign: { xs: "center", sm: "start", md: "start" },
|
variant="h6"
|
||||||
lineHeight: "1",
|
sx={{
|
||||||
marginBottom: "12px",
|
textAlign: { xs: "start", sm: "start", md: "start" },
|
||||||
}}
|
lineHeight: "1",
|
||||||
>
|
marginBottom: "12px",
|
||||||
Аналитика
|
}}
|
||||||
</Typography>
|
>
|
||||||
<YandexButton setIsModalOpen={setIsModalOpen} />
|
Аналитика
|
||||||
<YandexModal
|
</Typography>
|
||||||
isModalOpen={isModalOpen}
|
<Box
|
||||||
handleCloseModal={handleCloseModal}
|
sx={{
|
||||||
/>
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
justifyContent: { xs: "start", sm: "start", md: "start" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ServiceButton
|
||||||
|
logo={<YandexMetricaLogo />}
|
||||||
|
setIsModalOpen={setIsModalOpen}
|
||||||
|
name={"yandex"}
|
||||||
|
setCompanyName={setCompanyName}
|
||||||
|
/>
|
||||||
|
<ServiceButton
|
||||||
|
logo={<VKPixelLogo />}
|
||||||
|
title={"VK Пиксель"}
|
||||||
|
name={"vk"}
|
||||||
|
setIsModalOpen={setIsModalOpen}
|
||||||
|
setCompanyName={setCompanyName}
|
||||||
|
></ServiceButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
{companyName && (
|
||||||
|
<AnalyticsModal
|
||||||
|
isModalOpen={isModalOpen}
|
||||||
|
handleCloseModal={handleCloseModal}
|
||||||
|
companyName={companyName}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { Box, Typography, useTheme } from "@mui/material";
|
||||||
|
import { FC } from "react";
|
||||||
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
|
|
||||||
|
type PartnerItemProps = {
|
||||||
|
setIsModalOpen: (value: boolean) => void;
|
||||||
|
setCompanyName: (value: keyof typeof QuizMetricType) => void;
|
||||||
|
logo?: JSX.Element;
|
||||||
|
title?: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ServiceButton: FC<PartnerItemProps> = ({
|
||||||
|
setIsModalOpen,
|
||||||
|
logo,
|
||||||
|
title,
|
||||||
|
name,
|
||||||
|
setCompanyName,
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
setCompanyName(name as keyof typeof QuizMetricType);
|
||||||
|
setIsModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 250,
|
||||||
|
height: 60,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
padding: "0 20px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: "2%",
|
||||||
|
marginRight: "2%",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{logo && logo}
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "18px",
|
||||||
|
fontWeight: "400",
|
||||||
|
marginLeft: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title && title}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
10
src/pages/IntegrationsPage/mocks/VKLogo.svg
Normal file
10
src/pages/IntegrationsPage/mocks/VKLogo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 65 KiB |
6
src/pages/IntegrationsPage/mocks/VKPixelLogo.tsx
Normal file
6
src/pages/IntegrationsPage/mocks/VKPixelLogo.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ReactComponent as VKLogo } from "./VKLogo.svg";
|
||||||
|
|
||||||
|
export const VKPixelLogo = () => {
|
||||||
|
return <VKLogo />;
|
||||||
|
};
|
||||||
@ -50,19 +50,38 @@ export default function AvailablePrivilege() {
|
|||||||
const squizHideBadge = userPrivileges?.squizHideBadge?.amount || 0;
|
const squizHideBadge = userPrivileges?.squizHideBadge?.amount || 0;
|
||||||
|
|
||||||
//Где дни - amount - это на сколько дней выдан безлимит. т.е. не сколько осталось, а на сколько дней выдано
|
//Где дни - amount - это на сколько дней выдан безлимит. т.е. не сколько осталось, а на сколько дней выдано
|
||||||
function getCramps (amount: number, created_at: string) {
|
function getCramps(amount: number, created_at: string) {
|
||||||
if (created_at.length === 0) return 0
|
if (created_at.length === 0) return 0;
|
||||||
const currentDate = moment()
|
const currentDate = moment();
|
||||||
|
|
||||||
return Number((moment(moment(created_at).add(amount, "days").diff(currentDate)).unix() / 86400).toFixed(1))
|
return Number(
|
||||||
|
(
|
||||||
|
moment(
|
||||||
|
moment(created_at).add(amount, "days").diff(currentDate),
|
||||||
|
).unix() / 86400
|
||||||
|
).toFixed(1),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const quizUnlimDays = getCramps(quizUnlimTime, userPrivileges?.quizUnlimTime?.created_at || "")
|
const quizUnlimDays = getCramps(
|
||||||
const squizBadgeDays = getCramps(squizHideBadge, userPrivileges?.squizHideBadge?.created_at || "")
|
quizUnlimTime,
|
||||||
|
userPrivileges?.quizUnlimTime?.created_at || "",
|
||||||
|
);
|
||||||
|
const squizBadgeDays = getCramps(
|
||||||
|
squizHideBadge,
|
||||||
|
userPrivileges?.squizHideBadge?.created_at || "",
|
||||||
|
);
|
||||||
|
|
||||||
const currentDate = moment()
|
const currentDate = moment();
|
||||||
console.log(quizUnlimDays)
|
console.log(quizUnlimDays);
|
||||||
console.log(moment())
|
console.log(moment());
|
||||||
console.log(moment(moment(userPrivileges?.quizUnlimTime?.created_at).add(quizUnlimTime, "days")))
|
console.log(
|
||||||
|
moment(
|
||||||
|
moment(userPrivileges?.quizUnlimTime?.created_at).add(
|
||||||
|
quizUnlimTime,
|
||||||
|
"days",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -82,12 +101,9 @@ export default function AvailablePrivilege() {
|
|||||||
<Typography variant={"body1"} sx={{ color: "#4D4D4D" }}>
|
<Typography variant={"body1"} sx={{ color: "#4D4D4D" }}>
|
||||||
Безлимитные заявки:{" "}
|
Безлимитные заявки:{" "}
|
||||||
<strong>
|
<strong>
|
||||||
{
|
{quizUnlimDays > 0 && quizUnlimDays < 1
|
||||||
quizUnlimDays > 0 && quizUnlimDays < 1 ?
|
? "последний день"
|
||||||
"последний день"
|
: `${Math.trunc(quizUnlimDays)} ${declOfNum(Math.trunc(quizUnlimDays), DayForm)}`}
|
||||||
:
|
|
||||||
`${Math.trunc(quizUnlimDays)} ${declOfNum(Math.trunc(quizUnlimDays), DayForm)}`
|
|
||||||
}
|
|
||||||
</strong>
|
</strong>
|
||||||
</Typography>
|
</Typography>
|
||||||
{quizCnt !== 0 && (
|
{quizCnt !== 0 && (
|
||||||
@ -99,12 +115,9 @@ export default function AvailablePrivilege() {
|
|||||||
<Typography variant={"body1"} sx={{ color: "#4D4D4D" }}>
|
<Typography variant={"body1"} sx={{ color: "#4D4D4D" }}>
|
||||||
Скрытие логотипа PenaQuiz:{" "}
|
Скрытие логотипа PenaQuiz:{" "}
|
||||||
<strong>
|
<strong>
|
||||||
{
|
{squizBadgeDays > 0 && squizBadgeDays < 1
|
||||||
squizBadgeDays > 0 && squizBadgeDays < 1 ?
|
? "последний день"
|
||||||
"последний день"
|
: `${Math.trunc(squizBadgeDays)} ${declOfNum(Math.trunc(squizBadgeDays), DayForm)}`}
|
||||||
:
|
|
||||||
`${Math.trunc(squizBadgeDays)} ${declOfNum(Math.trunc(squizBadgeDays), DayForm)}`
|
|
||||||
}
|
|
||||||
</strong>
|
</strong>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -72,7 +72,6 @@ export const SidebarMobile: FC<Iprops> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const clickInput = (event: MouseEvent) => {
|
const clickInput = (event: MouseEvent) => {
|
||||||
debugger;
|
|
||||||
if (ref.current && !ref.current?.contains(event.target as Node))
|
if (ref.current && !ref.current?.contains(event.target as Node))
|
||||||
setInputOpen(false);
|
setInputOpen(false);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user