feat: correo via banco mail, rol supervisor y lint en cero
This commit is contained in:
1 parent
2502de4e06
commit
b1cddbac6c
15 files changed
+677
-107
No files matched your search
+77
-8
@@ -339,18 +339,20 @@ export async function updateSla(
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== Correo / plantillas ====================
|
||||
// ==================== Correo / plantillas (banco único mail.* vía /api/email/*) ====================
|
||||
export interface EmailTemplate {
|
||||
key: string;
|
||||
name: string;
|
||||
subject: string;
|
||||
bodyHtml: string;
|
||||
module?: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface EmailLogEntry {
|
||||
id: number;
|
||||
template: string;
|
||||
module?: string;
|
||||
ticketId?: number;
|
||||
recipient: string;
|
||||
subject: string;
|
||||
@@ -359,28 +361,95 @@ export interface EmailLogEntry {
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface EmailModule {
|
||||
module: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export async function getEmailTemplates() {
|
||||
return fetchApi<EmailTemplate[]>("/api/helpdesk/email/templates");
|
||||
return fetchApi<EmailTemplate[]>("/api/email/templates");
|
||||
}
|
||||
|
||||
export async function createEmailTemplate(data: {
|
||||
key: string;
|
||||
name: string;
|
||||
subject: string;
|
||||
bodyHtml: string;
|
||||
module?: string;
|
||||
}) {
|
||||
return fetchApi<{ key: string }>("/api/email/templates", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateEmailTemplate(
|
||||
key: string,
|
||||
data: { subject?: string; bodyHtml?: string; isActive?: boolean }
|
||||
) {
|
||||
return fetchApi<void>(`/api/helpdesk/email/templates/${encodeURIComponent(key)}`, {
|
||||
return fetchApi<void>(`/api/email/templates/${encodeURIComponent(key)}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
export async function getEmailLog(limit = 50) {
|
||||
return fetchApi<EmailLogEntry[]>(`/api/helpdesk/email/log?limit=${limit}`);
|
||||
export async function getEmailLog(limit = 50, module = "helpdesk") {
|
||||
const query = new URLSearchParams({ limit: String(limit) });
|
||||
if (module) query.set("module", module);
|
||||
return fetchApi<EmailLogEntry[]>(`/api/email/log?${query.toString()}`);
|
||||
}
|
||||
|
||||
export async function getEmailModules() {
|
||||
return fetchApi<EmailModule[]>("/api/email/modules");
|
||||
}
|
||||
|
||||
export async function registerEmailModule(module: string) {
|
||||
return fetchApi<{ module: string; apiKey: string }>("/api/email/modules", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ module }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function revokeEmailModule(module: string) {
|
||||
return fetchApi<{ module: string }>(`/api/email/modules/${encodeURIComponent(module)}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
// Envío vía route handler propio (/api/correos) → POST /api/email/send con
|
||||
// X-Module + X-Api-Key en el servidor (la clave nunca va en el bundle).
|
||||
// Reenvía el Bearer de admin para que el route verifique el rol.
|
||||
export async function sendModuleEmail(data: {
|
||||
to: string | string[];
|
||||
templateKey?: string;
|
||||
subject?: string;
|
||||
htmlBody?: string;
|
||||
vars?: Record<string, string | null>;
|
||||
}) {
|
||||
const token =
|
||||
typeof window !== "undefined" ? localStorage.getItem("helpdesk_token") : null;
|
||||
const res = await fetch("/api/correos", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const payload = await res.json().catch(() => ({}));
|
||||
if (!res.ok) {
|
||||
throw new Error(
|
||||
(payload as { message?: string }).message || `Error de envío: ${res.status}`
|
||||
);
|
||||
}
|
||||
return payload as { success: boolean; sent?: number; failed?: number; message?: string };
|
||||
}
|
||||
|
||||
export async function sendTestEmail(to: string) {
|
||||
return fetchApi<{ success: boolean; message?: string }>("/api/helpdesk/email/test", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ to }),
|
||||
return sendModuleEmail({
|
||||
to,
|
||||
subject: "[HelpDesk] Prueba de correo",
|
||||
htmlBody: `<p>Prueba de envío desde la Mesa de Ayuda ICHN (${new Date().toISOString().slice(0, 16).replace("T", " ")} UTC).</p><p>Vía banco <code>mail.templates</code> + <code>POST /api/email/send</code> (módulo helpdesk).</p>`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user