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:
@@ -199,6 +199,11 @@ export default function AppointmentsPage() {
|
|||||||
const [isClaimingAiColumn, setIsClaimingAiColumn] = useState(false);
|
const [isClaimingAiColumn, setIsClaimingAiColumn] = useState(false);
|
||||||
const [autoClaimEnabled, setAutoClaimEnabled] = useState(false);
|
const [autoClaimEnabled, setAutoClaimEnabled] = useState(false);
|
||||||
const [autoClaimTime, setAutoClaimTime] = useState("19:00");
|
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 autoClaimFiredHourRef = useRef<number | null>(null);
|
||||||
const [aiClaimModalOpen, setAiClaimModalOpen] = useState(false);
|
const [aiClaimModalOpen, setAiClaimModalOpen] = useState(false);
|
||||||
const [aiClaimQueue, setAiClaimQueue] = useState<ScheduledAppointment[]>([]);
|
const [aiClaimQueue, setAiClaimQueue] = useState<ScheduledAppointment[]>([]);
|
||||||
@@ -488,6 +493,7 @@ export default function AppointmentsPage() {
|
|||||||
sessionStorage.setItem("ai_claim_queue", JSON.stringify({ ...parsed, pendingResume: false }));
|
sessionStorage.setItem("ai_claim_queue", JSON.stringify({ ...parsed, pendingResume: false }));
|
||||||
setAiClaimQueue(queue);
|
setAiClaimQueue(queue);
|
||||||
setAiClaimCurrentIndex(0);
|
setAiClaimCurrentIndex(0);
|
||||||
|
setAiClaimAutoRun(!!parsed.autoRun);
|
||||||
setAiClaimModalOpen(true);
|
setAiClaimModalOpen(true);
|
||||||
processAiClaimAtIndex(queue, 0);
|
processAiClaimAtIndex(queue, 0);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -1652,13 +1658,16 @@ export default function AppointmentsPage() {
|
|||||||
toast({ title: "No unclaimed appointments", description: "All appointments in the selected columns are already claimed." });
|
toast({ title: "No unclaimed appointments", description: "All appointments in the selected columns are already claimed." });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const autoRun = autoConfirmEnabled || autoClaimEnabled;
|
||||||
sessionStorage.setItem("ai_claim_queue", JSON.stringify({
|
sessionStorage.setItem("ai_claim_queue", JSON.stringify({
|
||||||
appointments: unclaimed,
|
appointments: unclaimed,
|
||||||
date: formattedSelectedDate,
|
date: formattedSelectedDate,
|
||||||
pendingResume: false,
|
pendingResume: false,
|
||||||
|
autoRun,
|
||||||
}));
|
}));
|
||||||
setAiClaimQueue(unclaimed);
|
setAiClaimQueue(unclaimed);
|
||||||
setAiClaimCurrentIndex(0);
|
setAiClaimCurrentIndex(0);
|
||||||
|
setAiClaimAutoRun(autoRun);
|
||||||
setAiClaimModalOpen(true);
|
setAiClaimModalOpen(true);
|
||||||
await processAiClaimAtIndex(unclaimed, 0);
|
await processAiClaimAtIndex(unclaimed, 0);
|
||||||
};
|
};
|
||||||
@@ -1673,6 +1682,7 @@ export default function AppointmentsPage() {
|
|||||||
appointments: fromCurrent,
|
appointments: fromCurrent,
|
||||||
date: formattedSelectedDate,
|
date: formattedSelectedDate,
|
||||||
pendingResume: true,
|
pendingResume: true,
|
||||||
|
autoRun: aiClaimAutoRun,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
sessionStorage.removeItem("ai_claim_queue");
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SeleniumTaskBanner
|
<SeleniumTaskBanner
|
||||||
@@ -1907,6 +1939,19 @@ export default function AppointmentsPage() {
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</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">
|
<div className="flex items-center gap-2 border-l pl-3 ml-1">
|
||||||
<Switch
|
<Switch
|
||||||
id="auto-claim-toggle"
|
id="auto-claim-toggle"
|
||||||
@@ -2485,6 +2530,9 @@ export default function AppointmentsPage() {
|
|||||||
AI Claim Queue
|
AI Claim Queue
|
||||||
</h3>
|
</h3>
|
||||||
<span className="text-xs text-gray-500 font-medium">
|
<span className="text-xs text-gray-500 font-medium">
|
||||||
|
{aiClaimAutoRun && (
|
||||||
|
<span className="text-teal-600 mr-2">Auto</span>
|
||||||
|
)}
|
||||||
{aiClaimCurrentIndex + 1} / {aiClaimQueue.length}
|
{aiClaimCurrentIndex + 1} / {aiClaimQueue.length}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user