feat: correo grupal por departamento para avisos de ticket nuevo (IT al grupo)

This commit is contained in:
Nurfog committed 2026-10-01 16:01:50 -03:00
1 parent 8b59680588
commit f9dc520f65
2 files changed
+52 -5

No files matched your search

@@ -20,6 +20,7 @@ export default function DepartmentsPage() {
const [editing, setEditing] = useState<Group | null>(null);
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [notificationEmail, setNotificationEmail] = useState("");
const [isActive, setIsActive] = useState(true);
const [saving, setSaving] = useState(false);
const [modalError, setModalError] = useState("");
@@ -55,6 +56,7 @@ export default function DepartmentsPage() {
setEditing(null);
setName("");
setDescription("");
setNotificationEmail("");
setIsActive(true);
setModalError("");
setShowModal(true);
@@ -64,6 +66,7 @@ export default function DepartmentsPage() {
setEditing(g);
setName(g.name);
setDescription(g.description || "");
setNotificationEmail(g.notificationEmail || "");
setIsActive(g.isActive);
setModalError("");
setShowModal(true);
@@ -74,17 +77,27 @@ export default function DepartmentsPage() {
setModalError("El nombre es requerido");
return;
}
if (notificationEmail.trim() && !notificationEmail.includes("@")) {
setModalError("Correo de aviso inválido");
return;
}
setSaving(true);
setModalError("");
try {
const notifyValue = notificationEmail.trim() || null;
if (editing) {
await updateGroup(editing.id, {
name: name.trim(),
description: description.trim() || undefined,
isActive,
notificationEmail: notifyValue,
});
} else {
await createGroup({ name: name.trim(), description: description.trim() || undefined });
await createGroup({
name: name.trim(),
description: description.trim() || undefined,
notificationEmail: notifyValue,
});
}
setShowModal(false);
fetchGroups();
@@ -145,6 +158,7 @@ export default function DepartmentsPage() {
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>Correo de aviso</th>
<th>Estado</th>
<th className="text-end">Acciones</th>
</tr>
@@ -152,13 +166,13 @@ export default function DepartmentsPage() {
<tbody>
{loading ? (
<tr>
<td colSpan={4} className="text-center py-4">
<td colSpan={5} className="text-center py-4">
<div className="spinner-border spinner-border-sm text-primary" role="status"></div>
</td>
</tr>
) : groups.length === 0 ? (
<tr>
<td colSpan={4} className="empty-state">
<td colSpan={5} className="empty-state">
<i className="bi bi-diagram-3 d-block"></i>
<h5>Sin departamentos</h5>
<p className="text-muted mb-0">Crea el primero para organizar los tickets</p>
@@ -169,6 +183,16 @@ export default function DepartmentsPage() {
<tr key={g.id}>
<td className="fw-semibold">{g.name}</td>
<td className="text-muted">{g.description || "—"}</td>
<td className="text-muted" style={{ fontSize: "0.85rem" }}>
{g.notificationEmail ? (
<span title="Los avisos van a esta casilla y no a las personas">
<i className="bi bi-envelope-at me-1"></i>
{g.notificationEmail}
</span>
) : (
"Personas del depto."
)}
</td>
<td>
{g.isActive ? (
<span className="badge bg-success">Activo</span>
@@ -233,6 +257,19 @@ export default function DepartmentsPage() {
onChange={(e) => setDescription(e.target.value)}
/>
</div>
<div className="mb-3">
<label className="form-label">Correo de aviso (grupo)</label>
<input
type="email"
className="form-control"
value={notificationEmail}
onChange={(e) => setNotificationEmail(e.target.value)}
placeholder="ej: departamentodeinformatica@norteamericano.cl"
/>
<div className="form-text">
Si se define, los tickets nuevos avisan a esta casilla y no a las personas del departamento.
</div>
</div>
{editing && (
<div className="form-check form-switch">
<input
+12 -2
View File
@@ -244,6 +244,7 @@ export interface Group {
name: string;
description?: string;
isActive: boolean;
notificationEmail?: string | null;
}
export interface KBArticle {
@@ -288,7 +289,11 @@ export interface DashboardStats {
}
// ==================== Departamentos ====================
export async function createGroup(data: { name: string; description?: string }) {
export async function createGroup(data: {
name: string;
description?: string;
notificationEmail?: string | null;
}) {
return fetchApi<Group>("/api/helpdesk/groups", {
method: "POST",
body: JSON.stringify(data),
@@ -297,7 +302,12 @@ export async function createGroup(data: { name: string; description?: string })
export async function updateGroup(
id: number,
data: { name?: string; description?: string; isActive?: boolean }
data: {
name?: string;
description?: string;
isActive?: boolean;
notificationEmail?: string | null;
}
) {
return fetchApi<void>(`/api/helpdesk/groups/${id}`, {
method: "PUT",