feat: boton sincronizar respuestas por correo

This commit is contained in:
Nurfog committed 2026-09-14 15:51:33 -03:00
1 parent 2594c6a315
commit 2502de4e06
2 files changed
+62

No files matched your search

@@ -6,6 +6,7 @@ import {
updateEmailTemplate, updateEmailTemplate,
getEmailLog, getEmailLog,
sendTestEmail, sendTestEmail,
syncInboundEmail,
type EmailTemplate, type EmailTemplate,
type EmailLogEntry, type EmailLogEntry,
} from "@/lib/api"; } from "@/lib/api";
@@ -42,6 +43,8 @@ export default function EmailPage() {
const [testTo, setTestTo] = useState(""); const [testTo, setTestTo] = useState("");
const [testResult, setTestResult] = useState<{ ok: boolean; text: string } | null>(null); const [testResult, setTestResult] = useState<{ ok: boolean; text: string } | null>(null);
const [testing, setTesting] = useState(false); const [testing, setTesting] = useState(false);
const [syncing, setSyncing] = useState(false);
const [syncResult, setSyncResult] = useState<{ ok: boolean; text: string } | null>(null);
const fetchData = useCallback(async () => { const fetchData = useCallback(async () => {
setLoading(true); setLoading(true);
@@ -118,6 +121,24 @@ export default function EmailPage() {
} }
}; };
const handleSync = async () => {
setSyncing(true);
setSyncResult(null);
try {
const r = await syncInboundEmail();
setSyncResult({
ok: r.success,
text: r.success
? `Revisados: ${r.checkedCount}, agregados al ticket: ${r.inserted}, omitidos: ${r.skipped}${r.error ? ` (${r.error})` : ""}`
: r.error || "Error en la sincronización",
});
} catch (err) {
setSyncResult({ ok: false, text: err instanceof Error ? err.message : "Error en la sincronización" });
} finally {
setSyncing(false);
}
};
if (!authLoading && user?.role !== "admin") { if (!authLoading && user?.role !== "admin") {
return ( return (
<div> <div>
@@ -243,6 +264,37 @@ export default function EmailPage() {
</div> </div>
</div> </div>
<div className="card mb-4">
<div className="card-body">
<h6 className="fw-semibold mb-3">
<i className="bi bi-inbox me-2"></i>
Respuestas por correo
</h6>
{syncResult && (
<div className={`alert ${syncResult.ok ? "alert-success" : "alert-danger"} py-2`} role="alert">
{syncResult.text}
</div>
)}
<div className="d-flex gap-2">
<button className="btn btn-outline-primary" onClick={handleSync} disabled={syncing}>
{syncing ? (
<>
<span className="spinner-border spinner-border-sm me-2" role="status" />
Sincronizando...
</>
) : (
"Sincronizar ahora"
)}
</button>
</div>
<small className="text-muted d-block mt-2">
Lee la casilla Gmail y agrega como comentarios las respuestas con
etiqueta [HelpDesk HD-000123]. El worker lo hace solo cada 5 minutos.
Requiere scope gmail.readonly autorizado en admin.google.com.
</small>
</div>
</div>
<h6 className="fw-semibold mb-2"> <h6 className="fw-semibold mb-2">
<i className="bi bi-clock-history me-2"></i> <i className="bi bi-clock-history me-2"></i>
Últimos envíos Últimos envíos
+10
View File
@@ -383,3 +383,13 @@ export async function sendTestEmail(to: string) {
body: JSON.stringify({ to }), body: JSON.stringify({ to }),
}); });
} }
export async function syncInboundEmail() {
return fetchApi<{
success: boolean;
checkedCount: number;
inserted: number;
skipped: number;
error?: string;
}>("/api/helpdesk/email/inbound/sync", { method: "POST" });
}