feat(autocall): показ последних тест-звонков + честный статус задержки планировщика
This commit is contained in:
parent
0d8e0f9d40
commit
5e4bfc1af0
|
|
@ -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 = () => {
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ── Последние тест-звонки (контекст: что система уже делала) ───────── */}
|
||||
{lastTests.length > 0 && (
|
||||
<div className="mt-3">
|
||||
<div className="mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[var(--color-text-muted)]">
|
||||
Последние тест-звонки
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
{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 (
|
||||
<div key={t.id} className="flex flex-wrap items-center gap-x-3 gap-y-0.5 rounded-lg bg-[var(--color-surface)] px-2 py-1.5 text-[11px]">
|
||||
<span className="font-medium text-[var(--color-text)]">{fmtPhone(t.customer_phone)}</span>
|
||||
<span className={`text-[var(--color-text-muted)]`}>{tm.icon} {tm.label}</span>
|
||||
{slot && <span className="text-[var(--color-text-muted)]">· {slot}</span>}
|
||||
<span className="text-[10px] text-[var(--color-text-muted)]">· {fmtTime(t.created_at)}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Panel>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue