From 5e4bfc1af07fc6b83d0de39c19f39c8e60cd0ba2 Mon Sep 17 00:00:00 2001 From: Hermes Date: Wed, 2 Sep 2026 11:37:16 +0200 Subject: [PATCH] =?UTF-8?q?feat(autocall):=20=D0=BF=D0=BE=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D0=BD=D0=B8=D1=85?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82-=D0=B7=D0=B2=D0=BE=D0=BD=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=20+=20=D1=87=D0=B5=D1=81=D1=82=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B8=20=D0=BF=D0=BB=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D1=89=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/autocall/TestCallPanel.jsx | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/components/admin/autocall/TestCallPanel.jsx b/src/components/admin/autocall/TestCallPanel.jsx index 4a8faf3..dd8c1c5 100644 --- a/src/components/admin/autocall/TestCallPanel.jsx +++ b/src/components/admin/autocall/TestCallPanel.jsx @@ -52,8 +52,25 @@ export const TestCallPanel = () => { const [status, setStatus] = useState("idle"); // idle | queueing | queued | dialing | done | error const [result, setResult] = useState(null); // последняя строка autocall_log для этого теста const [startedAt, setStartedAt] = useState(null); + const [lastTests, setLastTests] = useState([]); // последние тест-звонки (для контекста) const pollRef = useRef(null); + // При монтировании показываем последние тестовые звонки, + // чтобы было видно, что система живая и что было в прошлый раз. + const loadLastTests = useCallback(async () => { + try { + const { data, error } = await supabase + .from("autocall_log") + .select("*") + .eq("was_test_mode", true) + .order("created_at", { ascending: false }) + .limit(3); + if (!error && data) setLastTests(data); + } catch { /* глушим */ } + }, []); + + useEffect(() => { loadLastTests(); }, [loadLastTests]); + const stopPolling = useCallback(() => { if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; } }, []); @@ -77,9 +94,9 @@ export const TestCallPanel = () => { }); if (error) throw error; setStatus("queued"); - setResult({ outcome: "queued", note: "Запрос поставлен в очередь. Планировщик создаст звонок." }); + setResult({ outcome: "queued", note: "Запрос в очереди. Планировщик обрабатывает её раз в ~5 минут — ожидайте звонок." }); // Начинаем поллить результат по нашему номеру с момента запуска - pollRef.current = setInterval(() => pollResult(now), 3000); + pollRef.current = setInterval(() => pollResult(now), 4000); } catch (e) { console.error("Test call queue error:", e); setStatus("error"); @@ -107,6 +124,7 @@ export const TestCallPanel = () => { // Как только есть финальный исход (не in_progress) — стоп if (["confirmed","confirmed_kept_previous","confirmed_silent","no_answer","no_input_day","no_input_half","operator","opt_out","invalid_number","error"].includes(row.outcome)) { stopPolling(); + loadLastTests(); } } else { setStatus((s) => (s === "dialing" ? "dialing" : "queued")); @@ -115,7 +133,7 @@ export const TestCallPanel = () => { // глуши, поллинг продолжит } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [phone, stopPolling]); + }, [phone, stopPolling, loadLastTests]); useEffect(() => () => stopPolling(), [stopPolling]); @@ -193,6 +211,31 @@ export const TestCallPanel = () => { )} )} + + {/* ── Последние тест-звонки (контекст: что система уже делала) ───────── */} + {lastTests.length > 0 && ( +
+
+ Последние тест-звонки +
+
+ {lastTests.map((t) => { + const tm = OUTCOME_META[t.outcome] || OUTCOME_META.error; + const slot = t.dtmf_day || t.dtmf_half + ? `${DAY_LABEL[t.dtmf_day] || ""}${t.dtmf_day && t.dtmf_half ? ", " : ""}${HALF_LABEL[t.dtmf_half] || ""}`.trim() || "—" + : null; + return ( +
+ {fmtPhone(t.customer_phone)} + {tm.icon} {tm.label} + {slot && · {slot}} + · {fmtTime(t.created_at)} +
+ ); + })} +
+
+ )} ); };