Spaces:
Sleeping
Sleeping
File size: 3,778 Bytes
7af0bed | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | import { useState, useEffect, useCallback, useRef } from "react";
import { batchAPI } from "../api/client";
import RecipientInput from "./RecipientInput";
import EmailQueue from "./EmailQueue";
import toast from "react-hot-toast";
export default function BatchProcessor({ currentSubject, currentHtml }) {
const [batchQueue, setBatchQueue] = useState([]);
const [batchStats, setBatchStats] = useState({});
const [batchMode, setBatchMode] = useState("manual");
const [batchCurrentIdx, setBatchCurrentIdx] = useState(-1);
const [autoRunning, setAutoRunning] = useState(false);
const [loading, setLoading] = useState(false);
const pollRef = useRef(null);
const refreshBatchStatus = useCallback(async () => {
try {
const res = await batchAPI.getQueue();
setBatchQueue(res.data.queue);
setBatchStats(res.data.stats);
setBatchMode(res.data.mode);
setBatchCurrentIdx(res.data.current_index);
return res.data;
} catch (err) {
console.error("Failed to fetch batch queue", err);
}
}, []);
useEffect(() => {
refreshBatchStatus();
const interval = setInterval(refreshBatchStatus, 3000);
return () => clearInterval(interval);
}, [refreshBatchStatus]);
const handleBatchStart = async (profList, mode, delayMin, delayMax) => {
setLoading(true);
try {
await batchAPI.start(profList, mode, delayMin, delayMax);
toast.success("Batch started!");
refreshBatchStatus();
} catch (err) {
toast.error(err.response?.data?.detail || "Failed to start batch");
} finally {
setLoading(false);
}
};
const handleBatchApprove = async (index) => {
try {
await batchAPI.send(index);
toast.success("Email sent!");
refreshBatchStatus();
} catch (err) {
toast.error("Send failed");
}
};
const handleBatchSkip = async (index) => {
try {
await batchAPI.skip(index);
toast.success("Skipped");
refreshBatchStatus();
} catch {
toast.error("Skip failed");
}
};
const handleAutoRun = async () => {
setAutoRunning(true);
try {
await batchAPI.autoRun();
} catch (err) {
if (err.name !== "CanceledError") {
toast.error("Auto-run stopped or failed");
}
} finally {
setAutoRunning(false);
refreshBatchStatus();
}
};
const handleStopAuto = async () => {
try {
await batchAPI.stop();
setAutoRunning(false);
toast.success("Stopped");
} catch {
toast.error("Failed to stop");
}
};
return (
<div className="space-y-6">
<RecipientInput
onBatchStart={handleBatchStart}
loading={loading}
/>
{batchQueue.length > 0 && (
<div className="animate-slide-up">
<EmailQueue
queue={batchQueue}
currentIndex={batchCurrentIdx}
stats={batchStats}
batchMode={batchMode}
autoRunning={autoRunning}
onSelect={(idx) => setBatchCurrentIdx(idx)}
onApprove={handleBatchApprove}
onSkip={handleBatchSkip}
onAutoRun={handleAutoRun}
onStopAuto={handleStopAuto}
/>
</div>
)}
</div>
);
}
|