diff --git a/src/model/quizSettings.ts b/src/model/quizSettings.ts index b728326a..b068fbb2 100644 --- a/src/model/quizSettings.ts +++ b/src/model/quizSettings.ts @@ -118,6 +118,11 @@ export interface QuizConfig { vkMetricNumber: number | undefined; } +export enum QuizMetricType { + yandex = "yandexMetricNumber", + vk = "vkMetricNumber", +} + export type FormContactFieldName = | "name" | "email" diff --git a/src/pages/IntegrationsPage/IntegrationYandex/YandexButton.tsx b/src/pages/IntegrationsPage/IntegrationYandex/YandexButton.tsx deleted file mode 100644 index 89d55334..00000000 --- a/src/pages/IntegrationsPage/IntegrationYandex/YandexButton.tsx +++ /dev/null @@ -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 = ({ - setIsModalOpen, - setCompanyName, -}) => { - const theme = useTheme(); - - const handleClick = () => { - setIsModalOpen(true); - }; - - return ( - <> - setIsModalOpen(true)} - > - - - - ); -}; diff --git a/src/pages/IntegrationsPage/IntegrationYandex/YandexModal.tsx b/src/pages/IntegrationsPage/IntegrationYandex/YandexModal.tsx deleted file mode 100644 index da6fd076..00000000 --- a/src/pages/IntegrationsPage/IntegrationYandex/YandexModal.tsx +++ /dev/null @@ -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(!!yandexNumber); - const [currentValue, setCurrentValue] = useState( - 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 ( - - - - Аналитика с Яндекс.Метрикой - - - - - - - - - - {isSave ? "Ваш номер счетчика" : "Введите номер счетчика"} - - {isSave && ( - - - - - - - - - )} - - - { - const onlyNums = e.target.value.replace(/[^0-9]/g, ""); - setCurrentValue(onlyNums); - }} - /> - - {!isSave && ( - - - - - )} - - - ); -} diff --git a/src/pages/IntegrationsPage/IntegrationsPage.tsx b/src/pages/IntegrationsPage/IntegrationsPage.tsx index c090b11a..7357dca1 100644 --- a/src/pages/IntegrationsPage/IntegrationsPage.tsx +++ b/src/pages/IntegrationsPage/IntegrationsPage.tsx @@ -6,6 +6,7 @@ import { useQuizStore } from "@root/quizes/store"; import { useNavigate } from "react-router-dom"; import { PartnersBoard } from "./PartnersBoard/PartnersBoard"; import { partnersMock } from "./mocks/MockData"; +import { QuizMetricType } from "@model/quizSettings"; interface IntegrationsPageProps { heightSidebar: number; @@ -22,7 +23,9 @@ export const IntegrationsPage = ({ const navigate = useNavigate(); const isMobile = useMediaQuery(theme.breakpoints.down(660)); const [isModalOpen, setIsModalOpen] = useState(false); - const [companyName, setCompanyName] = useState(null); + const [companyName, setCompanyName] = useState< + keyof typeof QuizMetricType | null + >(null); useEffect(() => { if (editQuizId === null) navigate("/list"); }, [navigate, editQuizId]); @@ -62,6 +65,7 @@ export const IntegrationsPage = ({ 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(!!meterNumber); + const [currentValue, setCurrentValue] = useState( + 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 ( + + + + Аналитика с {analyticTexts[companyName]?.header} + + + + + + + + + + {isSave + ? `Ваш номер ${analyticTexts[companyName]?.counterName}` + : `Введите номер ${analyticTexts[companyName]?.counterName}`} + + {isSave && ( + + + + + + + + + )} + + + { + const onlyNums = e.target.value.replace(/[^0-9]/g, ""); + setCurrentValue(onlyNums); + }} + /> + {!isSave && ( + + {meterNumber && !isSave && ( + + )} + + + )} + + + + + + ); +} diff --git a/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/InstructionsBlock.tsx b/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/InstructionsBlock.tsx new file mode 100644 index 00000000..afa87ee1 --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/InstructionsBlock.tsx @@ -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 = ({ + headerText, + instructionsText, + subHeaderText, + instructionTitle, +}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down(600)); + const [isInstructionOpen, setIsInstructionOpen] = useState(false); + return ( + + 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 && ( + + )} + + {headerText} + + + {subHeaderText} + + + {isInstructionOpen && ( + + + {instructionTitle} + + + {instructionsText} + + + )} + + ); +}; diff --git a/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx b/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx index adf54a60..e39d98e8 100644 --- a/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx +++ b/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx @@ -1,7 +1,10 @@ import { Box, Typography, useTheme } from "@mui/material"; import { FC } from "react"; -import { YandexButton } from "../IntegrationYandex/YandexButton"; -import YandexModal from "../IntegrationYandex/YandexModal"; +import { ServiceButton } from "./ServiceButton/ServiceButton"; +import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo"; +import AnalyticsModal from "./AnalyticsModal/AnalyticsModal"; +import { VKPixelLogo } from "../mocks/VKPixelLogo"; +import { QuizMetricType } from "@model/quizSettings"; export type Partner = { name: string; @@ -12,7 +15,8 @@ export type Partner = { type PartnersBoardProps = { partners: Partner[]; setIsModalOpen: (value: boolean) => void; - setCompanyName: (value: string) => void; + companyName: keyof typeof QuizMetricType | null; + setCompanyName: (value: keyof typeof QuizMetricType) => void; isModalOpen: boolean; handleCloseModal: () => void; }; @@ -22,17 +26,18 @@ export const PartnersBoard: FC = ({ setIsModalOpen, isModalOpen, handleCloseModal, + companyName, setCompanyName, }) => { const theme = useTheme(); - const partnersByCategory = partners.reduce( - (acc, partner) => { - (acc[partner.category] = acc[partner.category] || []).push(partner); - return acc; - }, - {} as Record, - ); + // const partnersByCategory = partners.reduce( + // (acc, partner) => { + // (acc[partner.category] = acc[partner.category] || []).push(partner); + // return acc; + // }, + // {} as Record, + // ); return ( = ({ {/* */} {/* */} {/*))}*/} - - Аналитика - - - + + + + Аналитика + + + } + setIsModalOpen={setIsModalOpen} + name={"yandex"} + setCompanyName={setCompanyName} + /> + } + title={"VK Пиксель"} + name={"vk"} + setIsModalOpen={setIsModalOpen} + setCompanyName={setCompanyName} + > + + + {companyName && ( + + )} ); }; diff --git a/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx new file mode 100644 index 00000000..4773e19f --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx @@ -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 = ({ + setIsModalOpen, + logo, + title, + name, + setCompanyName, +}) => { + const theme = useTheme(); + + const handleClick = () => { + setCompanyName(name as keyof typeof QuizMetricType); + setIsModalOpen(true); + }; + + return ( + <> + + {logo && logo} + + {title && title} + + + + ); +}; diff --git a/src/pages/IntegrationsPage/mocks/VKLogo.svg b/src/pages/IntegrationsPage/mocks/VKLogo.svg new file mode 100644 index 00000000..af78b0d0 --- /dev/null +++ b/src/pages/IntegrationsPage/mocks/VKLogo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/pages/IntegrationsPage/mocks/VKPixelLogo.tsx b/src/pages/IntegrationsPage/mocks/VKPixelLogo.tsx new file mode 100644 index 00000000..059b8c67 --- /dev/null +++ b/src/pages/IntegrationsPage/mocks/VKPixelLogo.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import { ReactComponent as VKLogo } from "./VKLogo.svg"; + +export const VKPixelLogo = () => { + return ; +}; diff --git a/src/pages/createQuize/AvailablePrivilege.tsx b/src/pages/createQuize/AvailablePrivilege.tsx index 3d1cbd3b..abcdd9e0 100644 --- a/src/pages/createQuize/AvailablePrivilege.tsx +++ b/src/pages/createQuize/AvailablePrivilege.tsx @@ -50,19 +50,38 @@ export default function AvailablePrivilege() { const squizHideBadge = userPrivileges?.squizHideBadge?.amount || 0; //Где дни - amount - это на сколько дней выдан безлимит. т.е. не сколько осталось, а на сколько дней выдано - function getCramps (amount: number, created_at: string) { - if (created_at.length === 0) return 0 - const currentDate = moment() + function getCramps(amount: number, created_at: string) { + if (created_at.length === 0) return 0; + 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 squizBadgeDays = getCramps(squizHideBadge, userPrivileges?.squizHideBadge?.created_at || "") + const quizUnlimDays = getCramps( + quizUnlimTime, + userPrivileges?.quizUnlimTime?.created_at || "", + ); + const squizBadgeDays = getCramps( + squizHideBadge, + userPrivileges?.squizHideBadge?.created_at || "", + ); - const currentDate = moment() - console.log(quizUnlimDays) - console.log(moment()) - console.log(moment(moment(userPrivileges?.quizUnlimTime?.created_at).add(quizUnlimTime, "days"))) + const currentDate = moment(); + console.log(quizUnlimDays); + console.log(moment()); + console.log( + moment( + moment(userPrivileges?.quizUnlimTime?.created_at).add( + quizUnlimTime, + "days", + ), + ), + ); return ( Безлимитные заявки:{" "} - { - quizUnlimDays > 0 && quizUnlimDays < 1 ? - "последний день" - : - `${Math.trunc(quizUnlimDays)} ${declOfNum(Math.trunc(quizUnlimDays), DayForm)}` - } + {quizUnlimDays > 0 && quizUnlimDays < 1 + ? "последний день" + : `${Math.trunc(quizUnlimDays)} ${declOfNum(Math.trunc(quizUnlimDays), DayForm)}`} {quizCnt !== 0 && ( @@ -99,12 +115,9 @@ export default function AvailablePrivilege() { Скрытие логотипа PenaQuiz:{" "} - { - squizBadgeDays > 0 && squizBadgeDays < 1 ? - "последний день" - : - `${Math.trunc(squizBadgeDays)} ${declOfNum(Math.trunc(squizBadgeDays), DayForm)}` - } + {squizBadgeDays > 0 && squizBadgeDays < 1 + ? "последний день" + : `${Math.trunc(squizBadgeDays)} ${declOfNum(Math.trunc(squizBadgeDays), DayForm)}`} )} diff --git a/src/ui_kit/Sidebar/SidebarMobile.tsx b/src/ui_kit/Sidebar/SidebarMobile.tsx index 462361f3..4cf2b29f 100644 --- a/src/ui_kit/Sidebar/SidebarMobile.tsx +++ b/src/ui_kit/Sidebar/SidebarMobile.tsx @@ -72,7 +72,6 @@ export const SidebarMobile: FC = ({ }; const clickInput = (event: MouseEvent) => { - debugger; if (ref.current && !ref.current?.contains(event.target as Node)) setInputOpen(false); };