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)} +
+ ); + })} +
+
+ )} ); };