feat(email): confirm hub thread unlink

This commit is contained in:
cesnimda
2026-08-10 09:40:59 +02:00
parent 73ee095795
commit 1dabbeb233
3 changed files with 88 additions and 1 deletions
@@ -108,6 +108,7 @@ export default function CorrespondenceInboxPage() {
const [sendResult, setSendResult] = useState<EmailSendResult | null>(null);
const [sendError, setSendError] = useState<string | null>(null);
const [sending, setSending] = useState(false);
const [unlinkingThreadId, setUnlinkingThreadId] = useState<string | null>(null);
const load = useCallback(async () => {
setLoading(true);
@@ -281,6 +282,37 @@ export default function CorrespondenceInboxPage() {
setSendError(null);
};
const unlinkGmailThread = async (item: CorrespondenceInboxItem) => {
if (item.provider !== "gmail" || !item.externalThreadId || unlinkingThreadId) return;
if (!(await confirm({
title: "Unlink Gmail thread?",
message: `Remove this Gmail thread from ${item.companyName || "this job"} and return it to recruitment review? The provider copy is not deleted.`,
confirmLabel: "Unlink thread",
destructive: true,
}))) return;
setUnlinkingThreadId(item.externalThreadId);
try {
await api.post("/gmail/unlink-thread", {
jobApplicationId: item.jobApplicationId,
threadId: item.externalThreadId,
note: "Unlinked from Job email hub",
nextDecision: "review",
});
if (selectedMessageId === item.id) {
detailRequest.current += 1;
setSelectedMessageId(null);
setMessageDetail(null);
}
await load();
toast("Gmail thread returned to recruitment review.", "success");
} catch (error) {
toast(getApiErrorMessage(error, "Failed to unlink the Gmail thread."), "error");
} finally {
setUnlinkingThreadId(null);
}
};
return (
<Paper
sx={{
@@ -401,6 +433,11 @@ export default function CorrespondenceInboxPage() {
{item.attachmentCount > 0 ? <Chip size="small" label={`${item.attachmentCount} attachments`} variant="outlined" /> : null}
<Button size="small" variant="text" onClick={() => void showMessage(item)}>{selectedMessageId === item.id ? "Hide message" : "View message"}</Button>
<Button size="small" variant="text" onClick={() => navigate(`/jobs?open=${item.jobApplicationId}`)}>Open job</Button>
{item.provider === "gmail" && item.externalThreadId ? (
<Button size="small" color="warning" variant="text" disabled={unlinkingThreadId === item.externalThreadId} onClick={() => void unlinkGmailThread(item)}>
{unlinkingThreadId === item.externalThreadId ? "Unlinking…" : "Unlink thread"}
</Button>
) : null}
</Box>
</Box>
{selectedMessageId === item.id ? (