diff --git a/frontend/src/app/(app)/settings/departments/page.tsx b/frontend/src/app/(app)/settings/departments/page.tsx new file mode 100644 index 0000000..e35d8d8 --- /dev/null +++ b/frontend/src/app/(app)/settings/departments/page.tsx @@ -0,0 +1,228 @@ +"use client"; + +import { useEffect, useState, useCallback } from "react"; +import { + getGroups, + createGroup, + updateGroup, + deleteGroup, + type Group, +} from "@/lib/api"; +import Modal from "@/components/Modal"; + +export default function DepartmentsPage() { + const [groups, setGroups] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(""); + const [showModal, setShowModal] = useState(false); + const [editing, setEditing] = useState(null); + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + const [isActive, setIsActive] = useState(true); + const [saving, setSaving] = useState(false); + const [modalError, setModalError] = useState(""); + + const fetchGroups = useCallback(async () => { + setLoading(true); + setError(""); + try { + setGroups(await getGroups()); + } catch (err) { + setError(err instanceof Error ? err.message : "Error al cargar"); + setGroups([]); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { + fetchGroups(); + }, [fetchGroups]); + + const openCreate = () => { + setEditing(null); + setName(""); + setDescription(""); + setIsActive(true); + setModalError(""); + setShowModal(true); + }; + + const openEdit = (g: Group) => { + setEditing(g); + setName(g.name); + setDescription(g.description || ""); + setIsActive(g.isActive); + setModalError(""); + setShowModal(true); + }; + + const handleSubmit = async () => { + if (!name.trim()) { + setModalError("El nombre es requerido"); + return; + } + setSaving(true); + setModalError(""); + try { + if (editing) { + await updateGroup(editing.id, { + name: name.trim(), + description: description.trim() || undefined, + isActive, + }); + } else { + await createGroup({ name: name.trim(), description: description.trim() || undefined }); + } + setShowModal(false); + fetchGroups(); + } catch (err) { + setModalError(err instanceof Error ? err.message : "Error al guardar"); + } finally { + setSaving(false); + } + }; + + const handleDelete = async (g: Group) => { + if (!confirm(`¿Eliminar el departamento "${g.name}"?`)) return; + setError(""); + try { + await deleteGroup(g.id); + fetchGroups(); + } catch (err) { + setError(err instanceof Error ? err.message : "Error al eliminar"); + } + }; + + return ( +
+
+

Departamentos

+ +
+ + {error && ( +
+ + {error} +
+ )} + +
+
+
+ + + + + + + + + + + {loading ? ( + + + + ) : groups.length === 0 ? ( + + + + ) : ( + groups.map((g) => ( + + + + + + + )) + )} + +
NombreDescripciónEstadoAcciones
+
+
+ +
Sin departamentos
+

Crea el primero para organizar los tickets

+
{g.name}{g.description || "—"} + {g.isActive ? ( + Activo + ) : ( + Inactivo + )} + + + +
+
+
+
+ + setShowModal(false)} + onSubmit={handleSubmit} + submitting={saving} + > + {modalError && ( +
+ {modalError} +
+ )} +
+ + setName(e.target.value)} + placeholder="ej: Soporte Nivel 1" + autoFocus + /> +
+
+ +