feat: auto-confirm option for AI column claims (manual toggle + implied by Auto Claim)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 00:07:30 -04:00
co-authored by Claude Fable 5
parent 41bed21302
commit efb85d0b92
@@ -199,6 +199,11 @@ export default function AppointmentsPage() {
const [isClaimingAiColumn, setIsClaimingAiColumn] = useState(false);
const [autoClaimEnabled, setAutoClaimEnabled] = useState(false);
const [autoClaimTime, setAutoClaimTime] = useState("19:00");
const [autoConfirmEnabled, setAutoConfirmEnabled] = useState(
() => localStorage.getItem("ai_claim_auto_confirm") === "1"
);
// True while the current AI claim run should advance without manual Confirm clicks
const [aiClaimAutoRun, setAiClaimAutoRun] = useState(false);
const autoClaimFiredHourRef = useRef<number | null>(null);
const [aiClaimModalOpen, setAiClaimModalOpen] = useState(false);
const [aiClaimQueue, setAiClaimQueue] = useState<ScheduledAppointment[]>([]);
@@ -488,6 +493,7 @@ export default function AppointmentsPage() {
sessionStorage.setItem("ai_claim_queue", JSON.stringify({ ...parsed, pendingResume: false }));
setAiClaimQueue(queue);
setAiClaimCurrentIndex(0);
setAiClaimAutoRun(!!parsed.autoRun);
setAiClaimModalOpen(true);
processAiClaimAtIndex(queue, 0);
} catch {
@@ -1652,13 +1658,16 @@ export default function AppointmentsPage() {
toast({ title: "No unclaimed appointments", description: "All appointments in the selected columns are already claimed." });
return;
}
const autoRun = autoConfirmEnabled || autoClaimEnabled;
sessionStorage.setItem("ai_claim_queue", JSON.stringify({
appointments: unclaimed,
date: formattedSelectedDate,
pendingResume: false,
autoRun,
}));
setAiClaimQueue(unclaimed);
setAiClaimCurrentIndex(0);
setAiClaimAutoRun(autoRun);
setAiClaimModalOpen(true);
await processAiClaimAtIndex(unclaimed, 0);
};
@@ -1673,6 +1682,7 @@ export default function AppointmentsPage() {
appointments: fromCurrent,
date: formattedSelectedDate,
pendingResume: true,
autoRun: aiClaimAutoRun,
}));
} else {
sessionStorage.removeItem("ai_claim_queue");
@@ -1760,6 +1770,28 @@ export default function AppointmentsPage() {
}
};
// Auto mode: advance the AI claim queue without manual Confirm clicks.
// Confirms when codes matched, skips otherwise (incl. CDT clarifications, which need human input).
useEffect(() => {
if (!aiClaimModalOpen || !aiClaimAutoRun || isAiClaimProcessing) return;
if (aiClaimCdtClarification) {
const t = setTimeout(() => {
setAiClaimCdtClarification(null);
handleAiClaimSkip();
}, 1500);
return () => clearTimeout(t);
}
if (!aiClaimCurrentData) return;
const t = setTimeout(() => {
if (aiClaimCurrentData.matchedCodes.length > 0) {
handleAiClaimConfirm();
} else {
handleAiClaimSkip();
}
}, 1500);
return () => clearTimeout(t);
}, [aiClaimModalOpen, aiClaimAutoRun, isAiClaimProcessing, aiClaimCurrentData, aiClaimCdtClarification]);
return (
<div>
<SeleniumTaskBanner
@@ -1907,6 +1939,19 @@ export default function AppointmentsPage() {
</span>
</label>
))}
<div className="flex items-center gap-2 border-l pl-3 ml-1">
<Switch
id="auto-confirm-toggle"
checked={autoConfirmEnabled}
onCheckedChange={(v) => {
setAutoConfirmEnabled(v);
localStorage.setItem("ai_claim_auto_confirm", v ? "1" : "0");
}}
/>
<Label htmlFor="auto-confirm-toggle" className="text-sm font-medium cursor-pointer whitespace-nowrap">
Auto Confirm
</Label>
</div>
<div className="flex items-center gap-2 border-l pl-3 ml-1">
<Switch
id="auto-claim-toggle"
@@ -2485,6 +2530,9 @@ export default function AppointmentsPage() {
AI Claim Queue
</h3>
<span className="text-xs text-gray-500 font-medium">
{aiClaimAutoRun && (
<span className="text-teal-600 mr-2">Auto</span>
)}
{aiClaimCurrentIndex + 1} / {aiClaimQueue.length}
</span>
</div>