import { useEffect, useState, useMemo } from "react"; import { Plus, Trash2, Pencil, RefreshCcw } from "lucide-react"; import MaterialTable from "@material-table/core"; import { Project, ProjectInput, fetchProjects, createProject as apiCreateProject, updateProject as apiUpdateProject, deactivateProject as apiDeactivateProject, } from "../../api/projects"; import { fetchMeterTypes, type MeterType } from "../../api/meterTypes"; import { getCurrentUserRole, getCurrentUserProjectId } from "../../api/auth"; export default function ProjectsPage() { const userRole = useMemo(() => getCurrentUserRole(), []); const userProjectId = useMemo(() => getCurrentUserProjectId(), []); const isOperator = userRole?.toUpperCase() === 'OPERATOR'; const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(true); const [activeProject, setActiveProject] = useState(null); const [search, setSearch] = useState(""); const [showModal, setShowModal] = useState(false); const [editingId, setEditingId] = useState(null); const [meterTypes, setMeterTypes] = useState([]); const emptyForm: ProjectInput = { name: "", description: "", areaName: "", location: "", status: "ACTIVE", meterTypeId: null, }; const [form, setForm] = useState(emptyForm); const loadProjects = async () => { setLoading(true); try { const data = await fetchProjects(); setProjects(data); } catch (error) { console.error("Error loading projects:", error); setProjects([]); } finally { setLoading(false); } }; const visibleProjects = useMemo(() => { if (!isOperator) { return projects; } if (userProjectId) { return projects.filter(p => p.id === userProjectId); } return []; }, [projects, isOperator, userProjectId]); const loadMeterTypesData = async () => { try { const types = await fetchMeterTypes(); setMeterTypes(types); } catch (error) { console.error("Error loading meter types:", error); setMeterTypes([]); } }; useEffect(() => { loadProjects(); loadMeterTypesData(); }, []); const handleSave = async () => { try { if (editingId) { const updatedProject = await apiUpdateProject(editingId, form); setProjects((prev) => prev.map((p) => (p.id === editingId ? updatedProject : p)) ); } else { const newProject = await apiCreateProject(form); setProjects((prev) => [...prev, newProject]); } setShowModal(false); setEditingId(null); setForm(emptyForm); setActiveProject(null); } catch (error) { console.error("Error saving project:", error); alert( `Error saving project: ${ error instanceof Error ? error.message : "Please try again." }` ); } }; const handleDelete = async () => { if (!activeProject) return; const confirmDelete = window.confirm( `¿Estás seguro que quieres desactivar el proyecto "${activeProject.name}"?\n\nEl proyecto será desactivado (no eliminado) y cualquier usuario asignado será desvinculado.` ); if (!confirmDelete) return; try { const deactivatedProject = await apiDeactivateProject(activeProject.id); setProjects((prev) => prev.map((p) => (p.id === deactivatedProject.id ? deactivatedProject : p)) ); setActiveProject(null); alert(`Proyecto "${activeProject.name}" ha sido desactivado exitosamente.`); } catch (error) { console.error("Error deactivating project:", error); alert( `Error al desactivar el proyecto: ${ error instanceof Error ? error.message : "Por favor intenta de nuevo." }` ); } }; const openEditModal = () => { if (!activeProject) return; setEditingId(activeProject.id); setForm({ name: activeProject.name, description: activeProject.description ?? "", areaName: activeProject.areaName, location: activeProject.location ?? "", status: activeProject.status, meterTypeId: activeProject.meterTypeId ?? null, }); setShowModal(true); }; const openCreateModal = () => { setForm(emptyForm); setEditingId(null); setShowModal(true); }; const filtered = visibleProjects.filter((p) => `${p.name} ${p.areaName} ${p.description ?? ""}` .toLowerCase() .includes(search.toLowerCase()) ); return (
{/* HEADER */}

Project Management

Proyectos registrados

{!isOperator && ( )} {!isOperator && ( )} {!isOperator && ( )}
{/* SEARCH */} setSearch(e.target.value)} /> {/* TABLE */} { if (!rowData.meterTypeId) return "-"; const meterType = meterTypes.find(mt => mt.id === rowData.meterTypeId); return meterType ? ( {meterType.name} ) : "-"; } }, { title: "Descripción", field: "description", render: (rowData: Project) => rowData.description || "-" }, { title: "Ubicación", field: "location", render: (rowData: Project) => rowData.location || "-" }, { title: "Estado", field: "status", render: (rowData: Project) => ( {rowData.status} ), }, { title: "Creado", field: "createdAt", render: (rowData: Project) => new Date(rowData.createdAt).toLocaleDateString(), }, ]} data={filtered} onRowClick={(_, rowData) => setActiveProject(rowData as Project)} options={{ search: false, paging: true, pageSize: 10, pageSizeOptions: [10, 20, 50], sorting: true, rowStyle: (rowData) => ({ backgroundColor: activeProject?.id === (rowData as Project).id ? "#EEF2FF" : "#FFFFFF", }), }} localization={{ body: { emptyDataSourceMessage: loading ? "Cargando proyectos..." : "No hay proyectos. Haz clic en 'Agregar' para crear uno.", }, }} />
{/* MODAL */} {showModal && (

{editingId ? "Editar Proyecto" : "Agregar Proyecto"}

setForm({ ...form, name: e.target.value })} />
setForm({ ...form, areaName: e.target.value })} />