-
Gestión de Usuarios
+ /* ================= DATA ================= */
+ const loadData = () => {
+ const mock: Area[] = [
+ {
+ id: 1,
+ name: "GRH",
+ operators: [
+ {
+ id: 1,
+ loginName: "admin_grh",
+ isSuperAdmin: true,
+ isDisabled: false,
+ userName: "Juan Pérez",
+ cellPhone: "664-123-4567",
+ createdAt: "2024-01-10",
+ },
+ ],
+ children: [
+ {
+ id: 2,
+ name: "CESPT",
+ operators: [
+ {
+ id: 2,
+ loginName: "cespt_admin",
+ isSuperAdmin: false,
+ isDisabled: false,
+ userName: "Carlos Ruiz",
+ cellPhone: "664-555-8899",
+ createdAt: "2024-02-02",
+ },
+ ],
+ },
+ ],
+ },
+ ];
- {/* BOTONES ESTILO GHOST */}
-
-
-
-
+ setAreas(mock);
+ setSelectedArea(mock[0]);
+ setExpandedIds([1]);
+ setActiveOperator(null);
+ };
+
+ useEffect(() => {
+ loadData();
+ }, []);
+
+ /* ================= TREE ================= */
+ const toggleExpand = (id: number) => {
+ setExpandedIds(prev =>
+ prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]
+ );
+ };
+
+ const updateArea = (list: Area[]): Area[] =>
+ list.map(area => {
+ if (area.id === selectedArea?.id) {
+ const operators = editingId
+ ? area.operators.map(op =>
+ op.id === editingId ? { ...op, ...form } : op
+ )
+ : [...area.operators, { id: Date.now(), ...form }];
+
+ return { ...area, operators };
+ }
+ if (area.children) {
+ return { ...area, children: updateArea(area.children) };
+ }
+ return area;
+ });
+
+ /* ================= CRUD ================= */
+ const handleSave = () => {
+ setAreas(prev => {
+ const updated = updateArea(prev);
+
+ // 🔑 volver a apuntar al área actual actualizada
+ const refreshedArea = updated.find(
+ a => a.id === selectedArea?.id
+ ) || null;
+
+ setSelectedArea(refreshedArea);
+ return updated;
+ });
+
+ setShowModal(false);
+ setEditingId(null);
+ setForm(emptyOperator);
+ };
+
+ const handleEdit = () => {
+ if (!activeOperator) return;
+ setEditingId(activeOperator.id);
+ setForm({ ...activeOperator });
+ setShowModal(true);
+ };
+
+ const handleDelete = () => {
+ if (!selectedArea || !activeOperator) return;
+
+ const deleteFromTree = (list: Area[]): Area[] =>
+ list.map(area => {
+ if (area.id === selectedArea.id) {
+ return {
+ ...area,
+ operators: area.operators.filter(
+ op => op.id !== activeOperator.id
+ ),
+ };
+ }
+ if (area.children) {
+ return { ...area, children: deleteFromTree(area.children) };
+ }
+ return area;
+ });
+
+ setAreas(prev => deleteFromTree(prev));
+ setActiveOperator(null);
+ };
+
+ /* ================= FILTER ================= */
+ const filtered =
+ selectedArea?.operators.filter(
+ op =>
+ op.loginName.toLowerCase().includes(search.toLowerCase()) ||
+ op.userName.toLowerCase().includes(search.toLowerCase())
+ ) || [];
+
+ /* ================= TREE RENDER ================= */
+ const renderTree = (area: Area, level = 0) => {
+ const expanded = expandedIds.includes(area.id);
+
+ return (
+
+
setSelectedArea(area)}
+ >
+ {area.children && (
+
+ )}
+ {area.name}
+
+ {expanded &&
+ area.children?.map(child => renderTree(child, level + 1))}
+
+ );
+ };
+
+ const filteredOperators: Operator[] =
+ selectedArea?.operators.filter(op => {
+ const q = search.toLowerCase();
+ return (
+ op.loginName.toLowerCase().includes(q) ||
+ op.userName.toLowerCase().includes(q) ||
+ op.cellPhone.toLowerCase().includes(q)
+ );
+ }) || [];
+
+ /* ================= UI ================= */
+ return (
+
+ {/* SIDEBAR */}
+
+
+ Organizational Structure
+
+ {areas.map(a => renderTree(a))}
- {/* TABLA */}
-
+ {/* MAIN */}
+
+ {/* HEADER */}
+
+
+
Operator Management
+
{selectedArea?.name}
+
+
+
+ {/* ADD */}
+
+
+ {/* EDIT */}
+
+
+ {/* DELETE */}
+
+
+ {/* REFRESH */}
+
+
+
+
+
+
{/* SEARCH */}
-
-
+
setSearch(e.target.value)}
+ />
+
+
(
+
+ {rowData.isSuperAdmin ? "Yes" : "No"}
+
+ ),
+ },
+ {
+ title: "Status",
+ field: "isDisabled",
+ render: rowData => (
+
+ {rowData.isDisabled ? "Off" : "Active"}
+
+ ),
+ },
+ { title: "User", field: "userName" },
+ { title: "Phone", field: "cellPhone" },
+ { title: "Created", field: "createdAt", type: "date" },
+ ]}
+ data={filtered}
+ onRowClick={(event, rowData) => {
+ setActiveOperator(rowData as Operator);
+ }}
+ actions={[
+ {
+ icon: () => ,
+ tooltip: "Add Operator",
+ isFreeAction: true,
+ onClick: () => {
+ setForm(emptyOperator);
+ setEditingId(null);
+ setShowModal(true);
+ },
+ },
+ {
+ icon: () => ,
+ tooltip: "Edit Operator",
+ onClick: (event, rowData) => {
+ setActiveOperator(rowData as Operator);
+ setEditingId((rowData as Operator).id);
+ setForm({ ...(rowData as Operator) });
+ setShowModal(true);
+ },
+ },
+ {
+ icon: () => ,
+ tooltip: "Delete Operator",
+ onClick: (event, rowData) => {
+ setActiveOperator(rowData as Operator);
+ handleDelete();
+ },
+ },
+ ]}
+ options={{
+ actionsColumnIndex: -1,
+ search: false,
+ paging: true,
+ sorting: true,
+ headerStyle: {
+ textAlign: "center",
+ fontWeight: 600,
+ },
+ cellStyle: {
+ textAlign: "center",
+ },
+ maxBodyHeight: "400px",
+ tableLayout: "fixed",
+ rowStyle: rowData => ({
+ backgroundColor:
+ activeOperator?.id === (rowData as Operator).id
+ ? "#EEF2FF"
+ : "#FFFFFF",
+ }),
+ }}
+/>
+
+
+
+
+
+ {/* MODAL */}
+ {showModal && (
+
+
+
+ {editingId ? "Edit Operator" : "Add Operator"}
+
+
setSearch(e.target.value)}
- className="w-full pl-9 pr-3 py-2 border border-gray-300 rounded shadow-sm text-gray-700 text-sm focus:outline-none focus:ring-2 focus:ring-blue-300"
+ className="w-full border px-3 py-2 rounded"
+ placeholder="Login Name"
+ value={form.loginName}
+ onChange={e =>
+ setForm({ ...form, loginName: e.target.value })
+ }
/>
-
-
-
-
-
-
+ )}
);
}