z p модалки с корректными запросами
This commit is contained in:
parent
862ed4f395
commit
7da86c5b2e
@ -4,14 +4,14 @@ import { parseAxiosError } from "@utils/parse-error";
|
|||||||
export type LeadTargetType = "mail" | "telegram" | "whatsapp" | "webhook";
|
export type LeadTargetType = "mail" | "telegram" | "whatsapp" | "webhook";
|
||||||
|
|
||||||
export interface LeadTargetModel {
|
export interface LeadTargetModel {
|
||||||
ID: number;
|
id: number;
|
||||||
AccountID: string;
|
accountID: string;
|
||||||
Type: LeadTargetType;
|
type: LeadTargetType;
|
||||||
QuizID: number;
|
quizID: number;
|
||||||
Target: string;
|
target: string; // содержит подстроку "zapier" или "postback"
|
||||||
InviteLink?: string;
|
inviteLink?: string;
|
||||||
Deleted?: boolean;
|
deleted?: boolean;
|
||||||
CreatedAt?: string;
|
createdAt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz`;
|
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz`;
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box, Button }
|
|||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { Quiz } from "@/model/quiz/quiz";
|
import { Quiz } from "@/model/quiz/quiz";
|
||||||
import CustomTextField from "@/ui_kit/CustomTextField";
|
import CustomTextField from "@/ui_kit/CustomTextField";
|
||||||
import { createLeadTarget, getLeadTargetsByQuiz, deleteLeadTarget } from "@/api/leadtarget";
|
import { createLeadTarget, getLeadTargetsByQuiz, deleteLeadTarget, updateLeadTarget } from "@/api/leadtarget";
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
import InstructionYoutubeLink from "@/pages/IntegrationsPage/IntegrationsModal/InstructionYoutubeLink";
|
import InstructionYoutubeLink from "@/pages/IntegrationsPage/IntegrationsModal/InstructionYoutubeLink";
|
||||||
import { useSnackbar } from "notistack";
|
import { useSnackbar } from "notistack";
|
||||||
|
import { useLeadTargets } from "@/pages/IntegrationsPage/hooks/useLeadTargets";
|
||||||
|
|
||||||
type PostbackModalProps = {
|
type PostbackModalProps = {
|
||||||
isModalOpen: boolean;
|
isModalOpen: boolean;
|
||||||
@ -27,28 +28,26 @@ export const PostbackModal: FC<PostbackModalProps> = ({
|
|||||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const deleteLeadTargetsByQuizType = async (quizId: number, type: "webhook") => {
|
|
||||||
const [targets] = await getLeadTargetsByQuiz(quizId);
|
|
||||||
if (!targets || targets.length === 0) {
|
|
||||||
console.log("No targets found for deletion");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const toDelete = targets.filter(t => t.Type === type);
|
|
||||||
console.log("Targets to delete:", toDelete);
|
|
||||||
for (const t of toDelete) {
|
|
||||||
console.log("Deleting target with ID:", t.ID);
|
|
||||||
await deleteLeadTarget(t.ID);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async (values: { token: string; domain: string }) => {
|
const handleSubmit = async (values: { token: string; domain: string }) => {
|
||||||
const tokenValue = (values.token || "").trim();
|
const tokenValue = (values.token || "").trim();
|
||||||
const target = (values.domain || "").trim();
|
const target = (values.domain || "").trim();
|
||||||
try {
|
try {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
|
// 1) Асинхронно получаем текущие цели
|
||||||
|
const [items] = await getLeadTargetsByQuiz(quiz.backendId);
|
||||||
|
const existing = (items ?? []).filter((t) => t.type === "webhook");
|
||||||
|
console.log("Saving flow -> existing webhook targets:", existing);
|
||||||
if (!tokenValue && !target) {
|
if (!tokenValue && !target) {
|
||||||
await deleteLeadTargetsByQuizType(quiz.backendId, "webhook");
|
const deletePromises = existing.map((t) => deleteLeadTarget(t.id));
|
||||||
|
await Promise.all(deletePromises);
|
||||||
enqueueSnackbar("Postback удален", { variant: "success" });
|
enqueueSnackbar("Postback удален", { variant: "success" });
|
||||||
|
} else if (existing.length > 0) {
|
||||||
|
const [first, ...extra] = existing;
|
||||||
|
await Promise.all([
|
||||||
|
updateLeadTarget({ id: first.id, target }),
|
||||||
|
...extra.map((t) => deleteLeadTarget(t.id)),
|
||||||
|
]);
|
||||||
|
enqueueSnackbar("Postback обновлен", { variant: "success" });
|
||||||
} else {
|
} else {
|
||||||
await createLeadTarget({
|
await createLeadTarget({
|
||||||
type: "webhook",
|
type: "webhook",
|
||||||
@ -58,6 +57,8 @@ export const PostbackModal: FC<PostbackModalProps> = ({
|
|||||||
});
|
});
|
||||||
enqueueSnackbar("Postback сохранен", { variant: "success" });
|
enqueueSnackbar("Postback сохранен", { variant: "success" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar("Ошибка при сохранении", { variant: "error" });
|
enqueueSnackbar("Ошибка при сохранении", { variant: "error" });
|
||||||
} finally {
|
} finally {
|
||||||
@ -65,11 +66,18 @@ export const PostbackModal: FC<PostbackModalProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { isLoading, postbackTarget, refresh } = useLeadTargets(quiz?.backendId, isModalOpen);
|
||||||
|
|
||||||
const formik = useFormik<{ token: string; domain: string }>({
|
const formik = useFormik<{ token: string; domain: string }>({
|
||||||
initialValues: { token: "", domain: "" },
|
initialValues: { token: "", domain: postbackTarget?.target ?? "" },
|
||||||
onSubmit: handleSubmit,
|
onSubmit: handleSubmit,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
formik.setFieldValue("domain", postbackTarget?.target ?? "");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [postbackTarget?.target]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isModalOpen) {
|
if (isModalOpen) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -153,17 +161,21 @@ export const PostbackModal: FC<PostbackModalProps> = ({
|
|||||||
>
|
>
|
||||||
Домен
|
Домен
|
||||||
</Typography>
|
</Typography>
|
||||||
<CustomTextField
|
{isLoading ? (
|
||||||
id="postback-domain"
|
<Box sx={{ width: "100%", height: 44, borderRadius: "8px", bgcolor: "action.hover" }} />
|
||||||
placeholder="токен в формате ХХХХХХ"
|
) : (
|
||||||
value={formik.values.domain}
|
<CustomTextField
|
||||||
onChange={(e) => formik.setFieldValue("domain", e.target.value)}
|
id="postback-domain"
|
||||||
maxLength={150}
|
placeholder="токен в формате ХХХХХХ"
|
||||||
/>
|
value={formik.values.domain}
|
||||||
|
onChange={(e) => formik.setFieldValue("domain", e.target.value)}
|
||||||
|
maxLength={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
disabled={isSaving}
|
disabled={isSaving || isLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import { Dialog, IconButton, Typography, useMediaQuery, useTheme, Box, Button }
|
|||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import { Quiz } from "@/model/quiz/quiz";
|
import { Quiz } from "@/model/quiz/quiz";
|
||||||
import CustomTextField from "@/ui_kit/CustomTextField";
|
import CustomTextField from "@/ui_kit/CustomTextField";
|
||||||
import { createLeadTarget, getLeadTargetsByQuiz, deleteLeadTarget } from "@/api/leadtarget";
|
import { createLeadTarget, getLeadTargetsByQuiz, deleteLeadTarget, updateLeadTarget } from "@/api/leadtarget";
|
||||||
import { useFormik } from "formik";
|
import { useFormik } from "formik";
|
||||||
import InstructionYoutubeLink from "@/pages/IntegrationsPage/IntegrationsModal/InstructionYoutubeLink";
|
import InstructionYoutubeLink from "@/pages/IntegrationsPage/IntegrationsModal/InstructionYoutubeLink";
|
||||||
import { useSnackbar } from "notistack";
|
import { useSnackbar } from "notistack";
|
||||||
|
import { useLeadTargets } from "@/pages/IntegrationsPage/hooks/useLeadTargets";
|
||||||
|
|
||||||
type ZapierModalProps = {
|
type ZapierModalProps = {
|
||||||
isModalOpen: boolean;
|
isModalOpen: boolean;
|
||||||
@ -27,28 +28,30 @@ export const ZapierModal: FC<ZapierModalProps> = ({
|
|||||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const deleteLeadTargetsByQuizType = async (quizId: number, type: "webhook") => {
|
|
||||||
const [targets] = await getLeadTargetsByQuiz(quizId);
|
|
||||||
if (!targets || targets.length === 0) {
|
|
||||||
console.log("No targets found for deletion");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const toDelete = targets.filter(t => t.Type === type);
|
|
||||||
console.log("Targets to delete:", toDelete);
|
|
||||||
for (const t of toDelete) {
|
|
||||||
console.log("Deleting target with ID:", t.ID);
|
|
||||||
await deleteLeadTarget(t.ID);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async (values: { webhookUrl: string }) => {
|
const handleSubmit = async (values: { webhookUrl: string }) => {
|
||||||
const target = (values.webhookUrl || "").trim();
|
const target = (values.webhookUrl || "").trim();
|
||||||
try {
|
try {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
|
// 1) Асинхронно получаем текущие цели
|
||||||
|
const [items] = await getLeadTargetsByQuiz(quiz.backendId);
|
||||||
|
const existing = (items ?? []).filter((t) => t.type === "webhook");
|
||||||
|
console.log("Saving flow -> existing webhook targets:", existing);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
await deleteLeadTargetsByQuizType(quiz.backendId, "webhook");
|
// Пустое значение — удаляем все
|
||||||
|
const deletePromises = existing.map((t) => deleteLeadTarget(t.id));
|
||||||
|
await Promise.all(deletePromises);
|
||||||
enqueueSnackbar("Webhook удален", { variant: "success" });
|
enqueueSnackbar("Webhook удален", { variant: "success" });
|
||||||
|
} else if (existing.length > 0) {
|
||||||
|
// Уже существует — обновляем первый и удаляем все лишние
|
||||||
|
const [first, ...extra] = existing;
|
||||||
|
await Promise.all([
|
||||||
|
updateLeadTarget({ id: first.id, target }),
|
||||||
|
...extra.map((t) => deleteLeadTarget(t.id)),
|
||||||
|
]);
|
||||||
|
enqueueSnackbar("Webhook обновлен", { variant: "success" });
|
||||||
} else {
|
} else {
|
||||||
|
// Не существует — создаем
|
||||||
await createLeadTarget({
|
await createLeadTarget({
|
||||||
type: "webhook",
|
type: "webhook",
|
||||||
quizID: quiz.backendId,
|
quizID: quiz.backendId,
|
||||||
@ -56,6 +59,8 @@ export const ZapierModal: FC<ZapierModalProps> = ({
|
|||||||
});
|
});
|
||||||
enqueueSnackbar("Webhook сохранен", { variant: "success" });
|
enqueueSnackbar("Webhook сохранен", { variant: "success" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await refresh();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar("Ошибка при сохранении", { variant: "error" });
|
enqueueSnackbar("Ошибка при сохранении", { variant: "error" });
|
||||||
} finally {
|
} finally {
|
||||||
@ -63,11 +68,18 @@ export const ZapierModal: FC<ZapierModalProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { isLoading, zapierTarget, refresh } = useLeadTargets(quiz?.backendId, isModalOpen);
|
||||||
|
|
||||||
const formik = useFormik<{ webhookUrl: string }>({
|
const formik = useFormik<{ webhookUrl: string }>({
|
||||||
initialValues: { webhookUrl: "" },
|
initialValues: { webhookUrl: zapierTarget?.target ?? "" },
|
||||||
onSubmit: handleSubmit,
|
onSubmit: handleSubmit,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
formik.setFieldValue("webhookUrl", zapierTarget?.target ?? "");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [zapierTarget?.target]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isModalOpen) {
|
if (isModalOpen) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -160,15 +172,19 @@ export const ZapierModal: FC<ZapierModalProps> = ({
|
|||||||
gap: isMobile ? "10px" : "38px"
|
gap: isMobile ? "10px" : "38px"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CustomTextField
|
{isLoading ? (
|
||||||
id="zapier-webhook-url"
|
<Box sx={{ width: "100%", height: 44, borderRadius: "8px", bgcolor: "action.hover" }} />
|
||||||
placeholder="введите url здесь"
|
) : (
|
||||||
value={formik.values.webhookUrl}
|
<CustomTextField
|
||||||
onChange={(e) => formik.setFieldValue("webhookUrl", e.target.value)}
|
id="zapier-webhook-url"
|
||||||
maxLength={150}
|
placeholder="введите url здесь"
|
||||||
/>
|
value={formik.values.webhookUrl}
|
||||||
|
onChange={(e) => formik.setFieldValue("webhookUrl", e.target.value)}
|
||||||
|
maxLength={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
disabled={isSaving}
|
disabled={isSaving || isLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
|
|||||||
import { useQuizStore } from "@root/quizes/store";
|
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 { getLeadTargetsByQuiz } from "@/api/leadtarget";
|
import { getLeadTargetsByQuiz, LeadTargetModel } from "@/api/leadtarget";
|
||||||
import { QuizMetricType } from "@model/quizSettings";
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
|
|
||||||
interface IntegrationsPageProps {
|
interface IntegrationsPageProps {
|
||||||
@ -31,7 +31,9 @@ export const IntegrationsPage = ({
|
|||||||
const [isZapierModalOpen, setIsZapierModalOpen] = useState<boolean>(false);
|
const [isZapierModalOpen, setIsZapierModalOpen] = useState<boolean>(false);
|
||||||
const [isPostbackModalOpen, setIsPostbackModalOpen] = useState<boolean>(false);
|
const [isPostbackModalOpen, setIsPostbackModalOpen] = useState<boolean>(false);
|
||||||
const [leadTargetsLoaded, setLeadTargetsLoaded] = useState<boolean>(false);
|
const [leadTargetsLoaded, setLeadTargetsLoaded] = useState<boolean>(false);
|
||||||
const [leadTargets, setLeadTargets] = useState<any[] | null>(null);
|
const [leadTargets, setLeadTargets] = useState<LeadTargetModel[] | null>(null);
|
||||||
|
const [zapierTarget, setZapierTarget] = useState<LeadTargetModel | null>(null);
|
||||||
|
const [postbackTarget, setPostbackTarget] = useState<LeadTargetModel | null>(null);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -39,16 +41,34 @@ export const IntegrationsPage = ({
|
|||||||
}, [navigate, editQuizId]);
|
}, [navigate, editQuizId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Загрузка связанных с квизом данных интеграций при входе на страницу
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
if (!leadTargetsLoaded && quiz?.id) {
|
if (!leadTargetsLoaded && quiz?.id) {
|
||||||
const [items] = await getLeadTargetsByQuiz(quiz.backendId);
|
const [items] = await getLeadTargetsByQuiz(quiz.backendId);
|
||||||
setLeadTargets(items ?? []);
|
const list = items ?? [];
|
||||||
|
console.log("LeadTargets fetched:", list);
|
||||||
|
setLeadTargets(list);
|
||||||
|
const webhookOnly = list.filter((t) => t.type === "webhook");
|
||||||
|
console.log("Webhook-only targets:", webhookOnly);
|
||||||
|
const zapier = webhookOnly.find((t) => (t.target || "").toLowerCase().includes("zapier")) ?? null;
|
||||||
|
const postback = webhookOnly.find((t) => (t.target || "").toLowerCase().includes("postback")) ?? null;
|
||||||
|
console.log("Distributed targets:", { zapier, postback });
|
||||||
|
setZapierTarget(zapier);
|
||||||
|
setPostbackTarget(postback);
|
||||||
setLeadTargetsLoaded(true);
|
setLeadTargetsLoaded(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
load();
|
load();
|
||||||
}, [leadTargetsLoaded, quiz?.id]);
|
}, [leadTargetsLoaded, quiz?.id]);
|
||||||
|
|
||||||
|
const refreshLeadTargets = async () => {
|
||||||
|
if (!quiz?.id) return;
|
||||||
|
const [items] = await getLeadTargetsByQuiz(quiz.backendId);
|
||||||
|
const list = items ?? [];
|
||||||
|
setLeadTargets(list);
|
||||||
|
const webhookOnly = list.filter((t) => t.type === "webhook");
|
||||||
|
setZapierTarget(webhookOnly.find((t) => (t.target || "").toLowerCase().includes("zapier")) ?? null);
|
||||||
|
setPostbackTarget(webhookOnly.find((t) => (t.target || "").toLowerCase().includes("postback")) ?? null);
|
||||||
|
};
|
||||||
const heightBar = heightSidebar + 51 + 88 + 36 + 25;
|
const heightBar = heightSidebar + 51 + 88 + 36 + 25;
|
||||||
|
|
||||||
if (quiz === undefined)
|
if (quiz === undefined)
|
||||||
@ -103,6 +123,8 @@ export const IntegrationsPage = ({
|
|||||||
setIsPostbackModalOpen={setIsPostbackModalOpen}
|
setIsPostbackModalOpen={setIsPostbackModalOpen}
|
||||||
isPostbackModalOpen={isPostbackModalOpen}
|
isPostbackModalOpen={isPostbackModalOpen}
|
||||||
handleClosePostbackModal={handleClosePostbackModal}
|
handleClosePostbackModal={handleClosePostbackModal}
|
||||||
|
zapierTarget={zapierTarget}
|
||||||
|
postbackTarget={postbackTarget}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { YandexMetricaLogo } from "../mocks/YandexMetricaLogo";
|
|||||||
import { VKPixelLogo } from "../mocks/VKPixelLogo";
|
import { VKPixelLogo } from "../mocks/VKPixelLogo";
|
||||||
import { QuizMetricType } from "@model/quizSettings";
|
import { QuizMetricType } from "@model/quizSettings";
|
||||||
import { AmoCRMLogo } from "../mocks/AmoCRMLogo";
|
import { AmoCRMLogo } from "../mocks/AmoCRMLogo";
|
||||||
|
import type { LeadTargetModel } from "@/api/leadtarget";
|
||||||
import { useCurrentQuiz } from "@/stores/quizes/hooks";
|
import { useCurrentQuiz } from "@/stores/quizes/hooks";
|
||||||
|
|
||||||
const AnalyticsModal = lazy(() =>
|
const AnalyticsModal = lazy(() =>
|
||||||
@ -48,6 +49,8 @@ type PartnersBoardProps = {
|
|||||||
setIsPostbackModalOpen: (value: boolean) => void;
|
setIsPostbackModalOpen: (value: boolean) => void;
|
||||||
isPostbackModalOpen: boolean;
|
isPostbackModalOpen: boolean;
|
||||||
handleClosePostbackModal: () => void;
|
handleClosePostbackModal: () => void;
|
||||||
|
zapierTarget?: LeadTargetModel | null;
|
||||||
|
postbackTarget?: LeadTargetModel | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PartnersBoard: FC<PartnersBoardProps> = ({
|
export const PartnersBoard: FC<PartnersBoardProps> = ({
|
||||||
@ -65,6 +68,8 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
|
|||||||
setIsPostbackModalOpen,
|
setIsPostbackModalOpen,
|
||||||
isPostbackModalOpen,
|
isPostbackModalOpen,
|
||||||
handleClosePostbackModal,
|
handleClosePostbackModal,
|
||||||
|
zapierTarget,
|
||||||
|
postbackTarget,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
@ -173,6 +178,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
|
|||||||
handleCloseModal={handleCloseZapierModal}
|
handleCloseModal={handleCloseZapierModal}
|
||||||
companyName={companyName}
|
companyName={companyName}
|
||||||
quiz={quiz!}
|
quiz={quiz!}
|
||||||
|
currentTarget={zapierTarget ?? null}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
@ -183,6 +189,7 @@ export const PartnersBoard: FC<PartnersBoardProps> = ({
|
|||||||
handleCloseModal={handleClosePostbackModal}
|
handleCloseModal={handleClosePostbackModal}
|
||||||
companyName={companyName}
|
companyName={companyName}
|
||||||
quiz={quiz!}
|
quiz={quiz!}
|
||||||
|
currentTarget={postbackTarget ?? null}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
|
|||||||
50
src/pages/IntegrationsPage/hooks/useLeadTargets.ts
Normal file
50
src/pages/IntegrationsPage/hooks/useLeadTargets.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { getLeadTargetsByQuiz, LeadTargetModel } from "@/api/leadtarget";
|
||||||
|
|
||||||
|
type UseLeadTargetsResult = {
|
||||||
|
isLoading: boolean;
|
||||||
|
zapierTarget: LeadTargetModel | null;
|
||||||
|
postbackTarget: LeadTargetModel | null;
|
||||||
|
refresh: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useLeadTargets(quizBackendId: number | undefined, isOpen: boolean): UseLeadTargetsResult {
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const [zapierTarget, setZapierTarget] = useState<LeadTargetModel | null>(null);
|
||||||
|
const [postbackTarget, setPostbackTarget] = useState<LeadTargetModel | null>(null);
|
||||||
|
|
||||||
|
const load = useCallback(async () => {
|
||||||
|
if (!quizBackendId) return;
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const [items] = await getLeadTargetsByQuiz(quizBackendId);
|
||||||
|
const list = items ?? [];
|
||||||
|
console.log("LeadTargets fetched:", list);
|
||||||
|
const webhookOnly = list.filter((t) => t.type === "webhook");
|
||||||
|
console.log("Webhook-only targets:", webhookOnly);
|
||||||
|
const zapier = webhookOnly.find((t) => (t.target || "").toLowerCase().includes("zapier")) ?? null;
|
||||||
|
const postback = webhookOnly.find((t) => (t.target || "").toLowerCase().includes("postback")) ?? null;
|
||||||
|
console.log("Distributed targets:", { zapier, postback });
|
||||||
|
setZapierTarget(zapier);
|
||||||
|
setPostbackTarget(postback);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}, [quizBackendId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}, [isOpen, load]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isLoading,
|
||||||
|
zapierTarget,
|
||||||
|
postbackTarget,
|
||||||
|
refresh: load,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user