The GIMA data service layer provides utilities for managing application data, including user management, asset categories, and maintenance records. Currently implemented as client-side state management with mock data.
Overview
GIMA uses a client-side data management approach with React hooks and local state. Data services are primarily implemented within component files using React’s useState and useEffect hooks.
Architecture Pattern
- Client-side state: Local component state managed with React hooks
- Mock data: Development data from
/src/utils/mockUsers.ts
- Type safety: TypeScript interfaces from
/src/types/
- No external API: Currently no backend integration
User Management Service
User data operations as implemented in UserTable.tsx.
State Management
const [users, setUsers] = useState<User[]>(mockUsers);
const [busqueda, setBusqueda] = useState('');
Available Functions
Filter Users
Filters users based on search criteria.
Array of user objects to filter
Search term to filter by (searches name, email, department)
Filtered array of users matching search criteria
Implementation:
const usuariosFiltrados = users.filter(user =>
user.name.toLowerCase().includes(busqueda.toLowerCase()) ||
user.email.toLowerCase().includes(busqueda.toLowerCase()) ||
user.department.toLowerCase().includes(busqueda.toLowerCase())
);
Usage Example (from UserTable.tsx:67-71):
import { useState } from 'react';
import { User } from '@/types/user';
import { mockUsers } from '@/utils/mockUsers';
function UserTable() {
const [users, setUsers] = useState<User[]>(mockUsers);
const [busqueda, setBusqueda] = useState('');
const usuariosFiltrados = users.filter(user =>
user.name.toLowerCase().includes(busqueda.toLowerCase()) ||
user.email.toLowerCase().includes(busqueda.toLowerCase()) ||
user.department.toLowerCase().includes(busqueda.toLowerCase())
);
return (
<input
value={busqueda}
onChange={(e) => setBusqueda(e.target.value)}
/>
);
}
Delete User
Removes a user from the state by ID.
Unique identifier of the user to delete
Updates state by removing the user
Implementation (from UserTable.tsx:22-25):
const eliminarUsuario = (id: string) => {
const nuevosUsuarios = users.filter(user => user.id !== id);
setUsers(nuevosUsuarios);
};
Error Handling: No validation - assumes ID exists in array.
Create/Update User
Saves a new user or updates an existing one.
User data object with properties matching User interface
If provided, updates existing user; otherwise creates new user
Updates state with new or modified user
Implementation (from UserTable.tsx:47-64):
const guardarUsuario = (userData: any) => {
if (usuarioEditando) {
// Edit mode: update existing user
setUsers(users.map(u =>
u.id === usuarioEditando.id
? { ...userData, id: usuarioEditando.id }
: u
));
} else {
// Create mode: add new user
const nuevoUsuario: User = {
...userData,
id: Date.now().toString(), // Temporary ID
};
setUsers([...users, nuevoUsuario]);
}
cerrarModal();
};
Important Notes:
- Uses
Date.now() for temporary IDs (should be replaced with backend-generated IDs)
- No data persistence - state resets on page reload
- No validation on
userData parameter
Category Management Service
Asset category operations as implemented in categorias-activos/page.tsx.
State Management
const [categories, setCategories] = useState(initialCategories);
const [searchTerm, setSearchTerm] = useState("");
Available Functions
Filter Categories
Filters categories based on search term.
Array of category objects
Search term (searches by name and ID)
Filtered array of categories
Implementation (from categorias-activos/page.tsx:51-55):
const filteredCategories = categories.filter(
(cat) =>
cat.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
cat.id.toLowerCase().includes(searchTerm.toLowerCase()),
);
Delete Category
Removes a category with confirmation dialog.
Implementation (from categorias-activos/page.tsx:57-66):
const handleDeleteClick = (id: string) => {
setIdToDelete(id);
setIsAlertOpen(true);
};
const confirmDelete = () => {
setCategories(categories.filter((cat) => cat.id !== idToDelete));
setIsAlertOpen(false);
setIdToDelete(null);
};
Pattern: Uses two-step deletion with confirmation modal for safety.
Data Types
User Interface
Defined in src/types/user.ts:3-11:
export type UserEstado = 'available' | 'unavailable';
export interface User {
id: string;
iniciales: string;
name: string;
email: string;
rol: string;
department: string;
status: UserEstado;
}
Category Interface
Inline definition in categorias-activos/page.tsx:17-42:
interface Category {
id: string; // Format: "CAT-001"
name: string; // e.g., "COMPUTO", "MOBILIARIO"
description: string; // Detailed description
total: number; // Count of assets in category
}
Mock Data
Mock Users
Sample user data from src/utils/mockUsers.ts:3-41:
export const mockUsers: User[] = [
{
id: '1',
iniciales: 'FC',
name: 'Frank Chacon',
email: '[email protected]',
rol: 'Engineer',
department: 'frontend',
status: 'unavailable',
},
// ... more users
];
Usage:
import { mockUsers } from '@/utils/mockUsers';
const [users, setUsers] = useState<User[]>(mockUsers);
Utility Functions
cn (Class Name Utility)
Defined in src/lib/utils.ts:4-6:
Array of class names to merge (supports conditional classes)
Merged and deduplicated class string
Implementation:
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Usage Example (from Sidebar.tsx:59-63):
import { cn } from "@/lib/utils";
<aside
className={cn(
"bg-[#001F3F] text-white flex flex-col h-screen",
"transition-all duration-300",
isOpen ? "w-64" : "w-20"
)}
>
Error Handling Patterns
Current State
The application currently has minimal error handling:
- No try-catch blocks: Operations assume success
- No validation: User input is not validated before processing
- No error states: No UI feedback for failed operations
- No loading states: Except in login (simulated delay)
Recommended Improvements
// Add error boundaries
try {
const result = await saveUser(userData);
setUsers(result);
} catch (error) {
console.error('Failed to save user:', error);
showErrorToast('No se pudo guardar el usuario');
}
// Add validation
if (!userData.email || !isValidEmail(userData.email)) {
throw new Error('Email inválido');
}
Future Backend Integration
When integrating with a backend API, replace local state operations with API calls:
// Current (client-side)
const eliminarUsuario = (id: string) => {
setUsers(users.filter(user => user.id !== id));
};
// Future (with API)
const eliminarUsuario = async (id: string) => {
try {
await fetch(`/api/users/${id}`, { method: 'DELETE' });
setUsers(users.filter(user => user.id !== id));
} catch (error) {
console.error('Delete failed:', error);
}
};