import React, { useEffect, useCallback } from 'react'; import { Models } from 'appwrite'; import SearchBar from './SearchBar'; import DataTable, { Column } from './DataTable'; import Pagination from './Pagination'; import TableActions from './TableActions'; interface ProdutoListProps { produtos: Models.Document[]; loading: boolean; isCreating?: boolean; error: string | null; totalProdutos: number; currentPage: number; isChangingPage: boolean; pageSize: number; onEdit: (produto: Models.Document) => void; onDelete: (id: string) => Promise; onPrevPage: () => void; onNextPage: () => void; onSearch: (termo: string) => void; searchTerm?: string; } const ProdutoList: React.FC = ({ produtos, loading, isCreating = false, error, totalProdutos, currentPage, isChangingPage, pageSize, onEdit, onDelete, onPrevPage, onNextPage, onSearch, searchTerm = '' }) => { const totalPages = Math.ceil(totalProdutos / pageSize); const startItem = (currentPage - 1) * pageSize + 1; const endItem = Math.min(currentPage * pageSize, totalProdutos); const [search, setSearch] = React.useState(searchTerm); // Sincronizar o estado local com o searchTerm externo useEffect(() => { setSearch(searchTerm); }, [searchTerm]); // Debounce para busca em tempo real const debouncedSearch = useCallback( debounce((term: string) => { onSearch(term); }, 500), [onSearch] ); // Função para lidar com mudanças no campo de busca const handleSearchChange = (value: string) => { setSearch(value); debouncedSearch(value); }; const handleSearch = () => { onSearch(search); }; // Função debounce function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout; return (...args: Parameters) => { clearTimeout(timeout); timeout = setTimeout(() => func(...args), wait); }; } const handleDelete = async (id: string) => { // Popup de confirmação é tratado pela função onDelete await onDelete(id); }; const formatarPreco = (preco: number) => { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(preco || 0); }; const columns: Column[] = [ { key: 'nome', header: 'Nome do Produto', render: produto => { console.log('🔍 Debug Produto:', { id: produto.$id, nome: produto.nome, catalogoProdutos: produto['catalogo-produtos'], allKeys: Object.keys(produto) }); return produto.nome || produto['catalogo-produtos']?.descricao || 'N/A'; } }, { key: 'descricao', header: 'Descrição (Catálogo)', render: produto => produto['catalogo-produtos']?.descricao || 'N/A', className: 'max-w-xs' }, { key: 'codigo', header: 'Código', render: produto => produto['catalogo-produtos']?.['codigo-interno'] || produto['catalogo-produtos']?.['codigo-ean'] || produto.codigo || 'N/A' }, { key: 'estoque', header: 'Estoque', render: produto => { // Usar quantidade real do produto ou padrão se não informado const estoque = produto.quantidade || produto.estoque || 0; return ( 20 ? 'text-green-600' : estoque > 5 ? 'text-yellow-600' : 'text-red-600' }`}> {estoque > 0 ? `${estoque} unidades` : 'Sem estoque'} ); } }, { key: 'preco-fabrica', header: 'Preço Fábrica', render: produto => formatarPreco(produto['preco-original'] || produto['preco-fabrica']) }, { key: 'preco-atual', header: 'Preço Atual', render: produto => formatarPreco(produto['preco-atual'] || produto['preco-venda']) }, { key: 'laboratorio', header: 'Laboratório', render: produto => { const laboratorios = produto['catalogo-produtos']?.laboratorios; if (laboratorios && laboratorios.length > 0) { return laboratorios[0].nome || 'N/A'; } return produto.laboratorio || 'N/A'; } }, { key: 'categoria', header: 'Categoria', render: produto => produto['catalogo-produtos']?.categorias?.nome || produto.categoria || 'N/A' } ]; return ( <> {/* Barra de busca */}
{error && (
{error}
)} {isCreating && (
Criando novo produto...
)} {loading ? (
Carregando produtos...
) : ( <> ( onEdit(produto)} onDelete={() => handleDelete(produto.$id)} /> )} />
{totalProdutos > 0 ? ( <>Mostrando {startItem} - {endItem} de {totalProdutos} produtos ) : ( 'Total de produtos: 0' )}
)} ); }; export default ProdutoList;