import React, { useState, useEffect, useMemo } from 'react'; import { Search, Filter, Plus, Download, RefreshCw, ChevronDown, FileText, TrendingUp, Clock, AlertCircle, Package, DollarSign, Grid, List } from 'lucide-react'; import { usePurchaseOrders, PurchaseOrder, CreatePurchaseOrderRequest } from '../../api/hooks/useSuppliers'; import { useAuth } from '../../api/hooks/useAuth'; import PurchaseOrderCard from './PurchaseOrderCard'; import PurchaseOrderForm from './PurchaseOrderForm'; import Card from '../ui/Card'; import Button from '../ui/Button'; import LoadingSpinner from '../ui/LoadingSpinner'; interface PurchaseOrderFilters { search: string; supplier_id: string; status: string; priority: string; date_from: string; date_to: string; } const PurchaseOrderManagementPage: React.FC = () => { const { user } = useAuth(); const { purchaseOrders, purchaseOrder: selectedPurchaseOrder, statistics, ordersRequiringApproval, overdueOrders, isLoading, isCreating, error, pagination, loadPurchaseOrders, loadPurchaseOrder, loadStatistics, loadOrdersRequiringApproval, loadOverdueOrders, createPurchaseOrder, updateOrderStatus, approveOrder, sendToSupplier, cancelOrder, clearError, refresh, setPage } = usePurchaseOrders(); const [filters, setFilters] = useState({ search: '', supplier_id: '', status: '', priority: '', date_from: '', date_to: '' }); const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid'); const [showFilters, setShowFilters] = useState(false); const [showPurchaseOrderForm, setShowPurchaseOrderForm] = useState(false); const [selectedOrder, setSelectedOrder] = useState(null); // Load initial data useEffect(() => { if (user?.tenant_id) { loadPurchaseOrders(); loadStatistics(); loadOrdersRequiringApproval(); loadOverdueOrders(); } }, [user?.tenant_id]); // Apply filters useEffect(() => { const searchParams: any = {}; if (filters.search) { searchParams.search_term = filters.search; } if (filters.supplier_id) { searchParams.supplier_id = filters.supplier_id; } if (filters.status) { searchParams.status = filters.status; } if (filters.priority) { searchParams.priority = filters.priority; } if (filters.date_from) { searchParams.date_from = filters.date_from; } if (filters.date_to) { searchParams.date_to = filters.date_to; } loadPurchaseOrders(searchParams); }, [filters]); // Status options const statusOptions = [ { value: '', label: 'Todos los estados' }, { value: 'DRAFT', label: 'Borrador' }, { value: 'PENDING_APPROVAL', label: 'Pendiente Aprobación' }, { value: 'APPROVED', label: 'Aprobado' }, { value: 'SENT_TO_SUPPLIER', label: 'Enviado a Proveedor' }, { value: 'CONFIRMED', label: 'Confirmado' }, { value: 'PARTIALLY_RECEIVED', label: 'Recibido Parcial' }, { value: 'COMPLETED', label: 'Completado' }, { value: 'CANCELLED', label: 'Cancelado' }, { value: 'DISPUTED', label: 'En Disputa' } ]; // Priority options const priorityOptions = [ { value: '', label: 'Todas las prioridades' }, { value: 'LOW', label: 'Baja' }, { value: 'NORMAL', label: 'Normal' }, { value: 'HIGH', label: 'Alta' }, { value: 'URGENT', label: 'Urgente' } ]; // Handle purchase order creation const handleCreatePurchaseOrder = async (orderData: CreatePurchaseOrderRequest) => { const order = await createPurchaseOrder(orderData); if (order) { setShowPurchaseOrderForm(false); // Refresh statistics and special lists loadStatistics(); if (order.status === 'PENDING_APPROVAL') loadOrdersRequiringApproval(); } }; // Handle order approval const handleApproveOrder = async ( order: PurchaseOrder, action: 'approve' | 'reject', notes?: string ) => { const updatedOrder = await approveOrder(order.id, action, notes); if (updatedOrder) { // Refresh relevant lists loadOrdersRequiringApproval(); loadStatistics(); } }; // Handle send to supplier const handleSendToSupplier = async (order: PurchaseOrder, sendEmail: boolean = true) => { const updatedOrder = await sendToSupplier(order.id, sendEmail); if (updatedOrder) { loadStatistics(); } }; // Handle cancel order const handleCancelOrder = async (order: PurchaseOrder, reason: string) => { const updatedOrder = await cancelOrder(order.id, reason); if (updatedOrder) { loadStatistics(); } }; // Handle clear filters const handleClearFilters = () => { setFilters({ search: '', supplier_id: '', status: '', priority: '', date_from: '', date_to: '' }); }; // Format currency const formatCurrency = (amount: number) => { return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(amount); }; // Statistics cards data const statsCards = useMemo(() => { if (!statistics) return []; return [ { title: 'Total Pedidos', value: statistics.total_orders.toString(), icon: FileText, color: 'blue' }, { title: 'Este Mes', value: statistics.this_month_orders.toString(), icon: TrendingUp, color: 'green' }, { title: 'Pendientes Aprobación', value: statistics.pending_approval.toString(), icon: Clock, color: 'yellow' }, { title: 'Gasto Este Mes', value: formatCurrency(statistics.this_month_spend), icon: DollarSign, color: 'purple' } ]; }, [statistics]); if (isLoading && !purchaseOrders.length) { return (
); } return (
{/* Header */}

Órdenes de Compra

Gestiona tus pedidos y compras a proveedores

{/* Error display */} {error && (
{error}
)} {/* Statistics Cards */}
{statsCards.map((stat, index) => (

{stat.title}

{stat.value}

))}
{/* Quick Lists */} {(ordersRequiringApproval.length > 0 || overdueOrders.length > 0) && (
{/* Orders Requiring Approval */} {ordersRequiringApproval.length > 0 && (

Requieren Aprobación

{ordersRequiringApproval.length}
{ordersRequiringApproval.slice(0, 3).map(order => ( setSelectedOrder(order)} /> ))} {ordersRequiringApproval.length > 3 && ( )}
)} {/* Overdue Orders */} {overdueOrders.length > 0 && (

Pedidos Vencidos

{overdueOrders.length}
{overdueOrders.slice(0, 3).map(order => ( setSelectedOrder(order)} /> ))} {overdueOrders.length > 3 && ( )}
)}
)} {/* Filters and Search */}
{/* Search */}
setFilters(prev => ({ ...prev, search: e.target.value }))} className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-64" />
{/* Filter Toggle */} {/* Active filters indicator */} {(filters.status || filters.priority || filters.supplier_id || filters.date_from || filters.date_to) && (
Filtros activos: {filters.status && ( {statusOptions.find(opt => opt.value === filters.status)?.label} )} {filters.priority && ( {priorityOptions.find(opt => opt.value === filters.priority)?.label} )}
)}
{/* View Mode Toggle */}
{/* Expanded Filters */} {showFilters && (
setFilters(prev => ({ ...prev, date_from: e.target.value }))} className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
)}
{/* Purchase Orders List */}
{purchaseOrders.length === 0 ? (

No se encontraron pedidos

{filters.search || filters.status || filters.priority ? 'Intenta ajustar tus filtros de búsqueda' : 'Comienza creando tu primera orden de compra' }

{!(filters.search || filters.status || filters.priority) && ( )}
) : (
{purchaseOrders.map(order => ( { setSelectedOrder(order); setShowPurchaseOrderForm(true); }} onViewDetails={(order) => setSelectedOrder(order)} onApprove={handleApproveOrder} onSendToSupplier={handleSendToSupplier} onCancel={handleCancelOrder} /> ))}
)} {/* Pagination */} {purchaseOrders.length > 0 && pagination.totalPages > 1 && (
Mostrando {((pagination.page - 1) * pagination.limit) + 1} a{' '} {Math.min(pagination.page * pagination.limit, pagination.total)} de{' '} {pagination.total} pedidos
{pagination.page}
)}
{/* Purchase Order Form Modal */} {showPurchaseOrderForm && ( { // Handle update logic here if needed setShowPurchaseOrderForm(false); setSelectedOrder(null); } : handleCreatePurchaseOrder } onClose={() => { setShowPurchaseOrderForm(false); setSelectedOrder(null); }} /> )}
); }; export default PurchaseOrderManagementPage;