From 80de8be2879490b0d8212377edd1a9e6b02623b4 Mon Sep 17 00:00:00 2001 From: Nastya Date: Sat, 9 Aug 2025 02:26:20 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B2=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/logo/Postback.tsx | 15 ++ src/assets/icons/logo/PostbackPC.tsx | 19 +++ src/assets/icons/logo/zapier.png | Bin 0 -> 3475 bytes src/model/quizSettings.ts | 2 + .../IntegrationsModal/Postback/index.tsx | 75 ++++++++++ .../IntegrationsModal/Zapier/index.tsx | 75 ++++++++++ .../IntegrationsPage/IntegrationsPage.tsx | 16 +- .../PartnersBoard/PartnersBoard.tsx | 140 ++++++++++++------ .../ServiceButton/ServiceButton.tsx | 57 ------- .../buttons/IntegrationButton.tsx | 53 +++++++ .../PartnersBoard/buttons/PostbackButton.tsx | 32 ++++ .../PartnersBoard/buttons/ServiceButton.tsx | 40 +++++ .../PartnersBoard/buttons/ZapierButton.tsx | 35 +++++ 13 files changed, 456 insertions(+), 103 deletions(-) create mode 100644 src/assets/icons/logo/Postback.tsx create mode 100644 src/assets/icons/logo/PostbackPC.tsx create mode 100644 src/assets/icons/logo/zapier.png create mode 100644 src/pages/IntegrationsPage/IntegrationsModal/Postback/index.tsx create mode 100644 src/pages/IntegrationsPage/IntegrationsModal/Zapier/index.tsx delete mode 100644 src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx create mode 100644 src/pages/IntegrationsPage/PartnersBoard/buttons/IntegrationButton.tsx create mode 100644 src/pages/IntegrationsPage/PartnersBoard/buttons/PostbackButton.tsx create mode 100644 src/pages/IntegrationsPage/PartnersBoard/buttons/ServiceButton.tsx create mode 100644 src/pages/IntegrationsPage/PartnersBoard/buttons/ZapierButton.tsx diff --git a/src/assets/icons/logo/Postback.tsx b/src/assets/icons/logo/Postback.tsx new file mode 100644 index 00000000..23956784 --- /dev/null +++ b/src/assets/icons/logo/Postback.tsx @@ -0,0 +1,15 @@ +import { Box, SxProps } from "@mui/material"; + +export default (sx: SxProps) => ( + + + +); \ No newline at end of file diff --git a/src/assets/icons/logo/PostbackPC.tsx b/src/assets/icons/logo/PostbackPC.tsx new file mode 100644 index 00000000..1dff7213 --- /dev/null +++ b/src/assets/icons/logo/PostbackPC.tsx @@ -0,0 +1,19 @@ +import { Box, SxProps } from "@mui/material"; + +export default (sx: SxProps) => ( + + + + + +); \ No newline at end of file diff --git a/src/assets/icons/logo/zapier.png b/src/assets/icons/logo/zapier.png new file mode 100644 index 0000000000000000000000000000000000000000..53f20b391cbfa2a7f7c99ffcae71d17928b6a133 GIT binary patch literal 3475 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 Bog)AM literal 0 HcmV?d00001 diff --git a/src/model/quizSettings.ts b/src/model/quizSettings.ts index 50050301..f04e8151 100644 --- a/src/model/quizSettings.ts +++ b/src/model/quizSettings.ts @@ -69,6 +69,8 @@ export type QuizTheme = export enum QuizMetricType { yandex = "yandexMetricsNumber", vk = "vkMetricsNumber", + zapier = "zapierIntegration", + postback = "postbackIntegration", } export type FormContactFieldName = "name" | "email" | "phone" | "text" | "address"; diff --git a/src/pages/IntegrationsPage/IntegrationsModal/Postback/index.tsx b/src/pages/IntegrationsPage/IntegrationsModal/Postback/index.tsx new file mode 100644 index 00000000..3b7af294 --- /dev/null +++ b/src/pages/IntegrationsPage/IntegrationsModal/Postback/index.tsx @@ -0,0 +1,75 @@ +import { FC } from "react"; +import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { Quiz } from "@/model/quiz/quiz"; + +type PostbackModalProps = { + isModalOpen: boolean; + handleCloseModal: () => void; + companyName: string | null; + quiz: Quiz; +}; + +export const PostbackModal: FC = ({ + isModalOpen, + handleCloseModal, + companyName, + quiz +}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down(600)); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + + return ( + + + + + Интеграция с {companyName ? companyName : "Postback"} + + + + + + + + Интеграция с Postback находится в разработке. + + + + + ); +}; \ No newline at end of file diff --git a/src/pages/IntegrationsPage/IntegrationsModal/Zapier/index.tsx b/src/pages/IntegrationsPage/IntegrationsModal/Zapier/index.tsx new file mode 100644 index 00000000..39483a96 --- /dev/null +++ b/src/pages/IntegrationsPage/IntegrationsModal/Zapier/index.tsx @@ -0,0 +1,75 @@ +import { FC } from "react"; +import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { Quiz } from "@/model/quiz/quiz"; + +type ZapierModalProps = { + isModalOpen: boolean; + handleCloseModal: () => void; + companyName: string | null; + quiz: Quiz; +}; + +export const ZapierModal: FC = ({ + isModalOpen, + handleCloseModal, + companyName, + quiz +}) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down(600)); + const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + + return ( + + + + + Интеграция с {companyName ? companyName : "Zapier"} + + + + + + + + Интеграция с Zapier находится в разработке. + + + + + ); +}; \ No newline at end of file diff --git a/src/pages/IntegrationsPage/IntegrationsPage.tsx b/src/pages/IntegrationsPage/IntegrationsPage.tsx index b74e3650..ce2af29a 100644 --- a/src/pages/IntegrationsPage/IntegrationsPage.tsx +++ b/src/pages/IntegrationsPage/IntegrationsPage.tsx @@ -27,6 +27,8 @@ export const IntegrationsPage = ({ >(null); const [isAmoCrmModalOpen, setIsAmoCrmModalOpen] = useState(false); + const [isZapierModalOpen, setIsZapierModalOpen] = useState(false); + const [isPostbackModalOpen, setIsPostbackModalOpen] = useState(false); useEffect(() => { if (editQuizId === null) navigate("/list"); @@ -44,6 +46,12 @@ export const IntegrationsPage = ({ const handleCloseAmoSRMModal = () => { setIsAmoCrmModalOpen(false); }; + const handleCloseZapierModal = () => { + setIsZapierModalOpen(false); + }; + const handleClosePostbackModal = () => { + setIsPostbackModalOpen(false); + }; return ( <> @@ -60,7 +68,7 @@ export const IntegrationsPage = ({ > Интеграции @@ -73,6 +81,12 @@ export const IntegrationsPage = ({ setIsAmoCrmModalOpen={setIsAmoCrmModalOpen} isAmoCrmModalOpen={isAmoCrmModalOpen} handleCloseAmoSRMModal={handleCloseAmoSRMModal} + setIsZapierModalOpen={setIsZapierModalOpen} + isZapierModalOpen={isZapierModalOpen} + handleCloseZapierModal={handleCloseZapierModal} + setIsPostbackModalOpen={setIsPostbackModalOpen} + isPostbackModalOpen={isPostbackModalOpen} + handleClosePostbackModal={handleClosePostbackModal} /> diff --git a/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx b/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx index 6612b444..6cb28b6d 100644 --- a/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx +++ b/src/pages/IntegrationsPage/PartnersBoard/PartnersBoard.tsx @@ -1,13 +1,13 @@ -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; +import { Box, Typography, useTheme } from "@mui/material"; import React, { FC, lazy, Suspense } from "react"; -import { ServiceButton } from "./ServiceButton/ServiceButton"; +import { ServiceButton } from "./buttons/ServiceButton"; +import { ZapierButton } from "./buttons/ZapierButton"; +import { PostbackButton } from "./buttons/PostbackButton"; import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo"; -// import AnalyticsModal from "./AnalyticsModal/AnalyticsModal"; import { VKPixelLogo } from "../mocks/VKPixelLogo"; import { QuizMetricType } from "@model/quizSettings"; import { AmoCRMLogo } from "../mocks/AmoCRMLogo"; import { useCurrentQuiz } from "@/stores/quizes/hooks"; -import { useUserStore } from "@/stores/user"; const AnalyticsModal = lazy(() => import("./AnalyticsModal/AnalyticsModal").then((module) => ({ @@ -21,6 +21,18 @@ const AmoCRMModal = lazy(() => })) ); +const ZapierModal = lazy(() => + import("../IntegrationsModal/Zapier").then((module) => ({ + default: module.ZapierModal, + })) +); + +const PostbackModal = lazy(() => + import("../IntegrationsModal/Postback").then((module) => ({ + default: module.PostbackModal, + })) +); + type PartnersBoardProps = { setIsModalOpen: (value: boolean) => void; companyName: keyof typeof QuizMetricType | null; @@ -30,6 +42,12 @@ type PartnersBoardProps = { setIsAmoCrmModalOpen: (value: boolean) => void; isAmoCrmModalOpen: boolean; handleCloseAmoSRMModal: () => void; + setIsZapierModalOpen: (value: boolean) => void; + isZapierModalOpen: boolean; + handleCloseZapierModal: () => void; + setIsPostbackModalOpen: (value: boolean) => void; + isPostbackModalOpen: boolean; + handleClosePostbackModal: () => void; }; export const PartnersBoard: FC = ({ @@ -41,13 +59,31 @@ export const PartnersBoard: FC = ({ setIsAmoCrmModalOpen, isAmoCrmModalOpen, handleCloseAmoSRMModal, + setIsZapierModalOpen, + isZapierModalOpen, + handleCloseZapierModal, + setIsPostbackModalOpen, + isPostbackModalOpen, + handleClosePostbackModal, }) => { const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(600)); - const quiz = useCurrentQuiz(); - const user = useUserStore(); + const sectionTitleStyles = { + textAlign: { xs: "start", sm: "start", md: "start" } as const, + lineHeight: "1", + marginBottom: "12px", + marginTop: "20px", + color: theme.palette.grey3.main, + fontSize: "18px", + }; + + const containerStyles = { + display: "flex", + flexWrap: "wrap", + justifyContent: { xs: "start", sm: "start", md: "start" }, + gap: { xs: "15px", md: "20px" }, + }; return ( = ({ }} > - <> - - CRM - - - } - setIsModalOpen={setIsAmoCrmModalOpen} - setCompanyName={setCompanyName} - name={"amoCRM"} - /> - - + CRM + + + } + setIsModalOpen={setIsAmoCrmModalOpen} + setCompanyName={setCompanyName} + name={"amoCRM"} + /> + + + Аналитика - + } setIsModalOpen={setIsModalOpen} @@ -114,9 +129,24 @@ export const PartnersBoard: FC = ({ name={"vk"} setIsModalOpen={setIsModalOpen} setCompanyName={setCompanyName} - > + /> + + + + Автоматизация + + + + + {companyName && ( = ({ isModalOpen={isAmoCrmModalOpen} handleCloseModal={handleCloseAmoSRMModal} companyName={companyName} - quiz={quiz} + quiz={quiz!} + /> + + )} + {companyName && isZapierModalOpen && ( + + + + )} + {companyName && isPostbackModalOpen && ( + + )} diff --git a/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx deleted file mode 100644 index 4773e19f..00000000 --- a/src/pages/IntegrationsPage/PartnersBoard/ServiceButton/ServiceButton.tsx +++ /dev/null @@ -1,57 +0,0 @@ -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/PartnersBoard/buttons/IntegrationButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/buttons/IntegrationButton.tsx new file mode 100644 index 00000000..fe22cfd0 --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/buttons/IntegrationButton.tsx @@ -0,0 +1,53 @@ +import { Box } from "@mui/material"; +import { FC, useState, ReactNode } from "react"; + +type IntegrationButtonProps = { + children: ReactNode; + onClick: () => void; + padding?: string; +}; + +export const IntegrationButton: FC = ({ + children, + onClick, + padding = "0 20px", +}) => { + const [isPressed, setIsPressed] = useState(false); + + const handleMouseDown = () => setIsPressed(true); + const handleMouseUp = () => setIsPressed(false); + const handleMouseLeave = () => setIsPressed(false); + + return ( + + {children} + + ); +}; \ No newline at end of file diff --git a/src/pages/IntegrationsPage/PartnersBoard/buttons/PostbackButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/buttons/PostbackButton.tsx new file mode 100644 index 00000000..faf90d05 --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/buttons/PostbackButton.tsx @@ -0,0 +1,32 @@ +import { Box } from "@mui/material"; +import { FC } from "react"; +import { QuizMetricType } from "@model/quizSettings"; +import PostbackDefault from "@/assets/icons/logo/Postback"; +import PostbackPC from "@/assets/icons/logo/PostbackPC"; +import { IntegrationButton } from "./IntegrationButton"; + +type PostbackButtonProps = { + setIsModalOpen: (value: boolean) => void; + setCompanyName: (value: keyof typeof QuizMetricType) => void; +}; + +export const PostbackButton: FC = ({ + setIsModalOpen, + setCompanyName, +}) => { + const handleClick = () => { + setCompanyName("postback" as keyof typeof QuizMetricType); + setIsModalOpen(true); + }; + + return ( + + <> + {/* Иконка монитора */} + + {/* Текст Postback */} + + + + ); +}; \ No newline at end of file diff --git a/src/pages/IntegrationsPage/PartnersBoard/buttons/ServiceButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/buttons/ServiceButton.tsx new file mode 100644 index 00000000..88a92fce --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/buttons/ServiceButton.tsx @@ -0,0 +1,40 @@ +import { Typography } from "@mui/material"; +import { FC } from "react"; +import { QuizMetricType } from "@model/quizSettings"; +import { IntegrationButton } from "./IntegrationButton"; + +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 handleClick = () => { + setCompanyName(name as keyof typeof QuizMetricType); + setIsModalOpen(true); + }; + + return ( + + {logo && logo} + + {title && title} + + + ); +}; \ No newline at end of file diff --git a/src/pages/IntegrationsPage/PartnersBoard/buttons/ZapierButton.tsx b/src/pages/IntegrationsPage/PartnersBoard/buttons/ZapierButton.tsx new file mode 100644 index 00000000..8abcc70a --- /dev/null +++ b/src/pages/IntegrationsPage/PartnersBoard/buttons/ZapierButton.tsx @@ -0,0 +1,35 @@ +import { Box } from "@mui/material"; +import { FC } from "react"; +import { QuizMetricType } from "@model/quizSettings"; +import zapierLogo from "@/assets/icons/logo/zapier.png"; +import { IntegrationButton } from "./IntegrationButton"; + +type ZapierButtonProps = { + setIsModalOpen: (value: boolean) => void; + setCompanyName: (value: keyof typeof QuizMetricType) => void; +}; + +export const ZapierButton: FC = ({ + setIsModalOpen, + setCompanyName, +}) => { + const handleClick = () => { + setCompanyName("zapier" as keyof typeof QuizMetricType); + setIsModalOpen(true); + }; + + return ( + + + + ); +}; \ No newline at end of file