/** * ContratosPage - Lista de contratos */ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Plus, Eye, Pencil, Trash2, FileText, Building2, Calendar, DollarSign } from 'lucide-react'; import { useContracts, useDeleteContract, } from '../../../hooks/useContracts'; import { useSubcontractors } from '../../../hooks/useContracts'; import type { Contract, ContractType, ContractStatus, ContractFilters, } from '../../../types/contracts.types'; import { CONTRACT_TYPE_OPTIONS, CONTRACT_STATUS_OPTIONS, } from '../../../types/contracts.types'; import { PageHeader, PageHeaderAction, SearchInput, SelectField, StatusBadgeFromOptions, ConfirmDialog, LoadingOverlay, EmptyState, Pagination, } from '../../../components/common'; import { ContractForm } from '../../../components/contracts/ContractForm'; export function ContratosPage() { const navigate = useNavigate(); const [search, setSearch] = useState(''); const [typeFilter, setTypeFilter] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [subcontractorFilter, setSubcontractorFilter] = useState(''); const [page, setPage] = useState(1); const [showModal, setShowModal] = useState(false); const [editingItem, setEditingItem] = useState(null); const [deleteId, setDeleteId] = useState(null); const filters: ContractFilters = { search: search || undefined, contractType: typeFilter || undefined, status: statusFilter || undefined, subcontractorId: subcontractorFilter || undefined, page, limit: 10, }; const { data, isLoading, error } = useContracts(filters); const { data: subcontractorsData } = useSubcontractors({ status: 'active' }); const deleteMutation = useDeleteContract(); const contracts = data?.items || []; const total = data?.total || 0; const totalPages = Math.ceil(total / 10); const handleDelete = async () => { if (deleteId) { await deleteMutation.mutateAsync(deleteId); setDeleteId(null); } }; const handleView = (id: string) => { navigate(`/admin/contratos/${id}`); }; const handleEdit = (contract: Contract) => { setEditingItem(contract); setShowModal(true); }; const handleCreate = () => { setEditingItem(null); setShowModal(true); }; const formatCurrency = (value: number) => { return new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN', }).format(value); }; const formatDate = (dateStr: string) => { return new Date(dateStr).toLocaleDateString('es-MX', { year: 'numeric', month: 'short', day: 'numeric', }); }; if (isLoading) { return ; } if (error) { return ( ); } return (
Nuevo Contrato } /> {/* Filters */}
({ value: o.value, label: o.label })), ]} value={typeFilter} onChange={(e) => setTypeFilter(e.target.value as ContractType | '')} /> ({ value: o.value, label: o.label })), ]} value={statusFilter} onChange={(e) => setStatusFilter(e.target.value as ContractStatus | '')} /> ({ value: s.id, label: s.businessName, })), ]} value={subcontractorFilter} onChange={(e) => setSubcontractorFilter(e.target.value)} />
{/* Table */}
{contracts.length === 0 ? ( } title="No hay contratos" description="Crea el primer contrato para comenzar." /> ) : ( <>
{contracts.map((contract) => ( ))}
Contrato Tipo Cliente/Subcontratista Vigencia Monto Avance Estado Acciones
{contract.contractNumber}
{contract.name}
{contract.contractType === 'client' ? contract.clientName : contract.subcontractor?.businessName || '-'}
{formatDate(contract.startDate)} - {formatDate(contract.endDate)}
{formatCurrency(contract.contractAmount)}
{contract.progressPercentage}%
{totalPages > 1 && (
)} )}
{/* Modal */} {showModal && ( { setShowModal(false); setEditingItem(null); }} /> )} {/* Delete Confirmation */} setDeleteId(null)} onConfirm={handleDelete} title="Confirmar eliminacion" message="Esta seguro de eliminar este contrato? Esta accion no se puede deshacer." confirmLabel="Eliminar" variant="danger" isLoading={deleteMutation.isPending} />
); }