import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { ScrollArea } from "@/components/ui/scroll-area"; import { toast } from 'sonner'; import { Search, Package, Shield, AlertTriangle, Settings } from 'lucide-react'; import { useDebounce } from '@/hooks/useDebounce'; import { Peca } from '@/hooks/usePecas'; import { useComponentesPeca } from '@/hooks/useComponentesPeca'; import { useUserRole } from '@/hooks/useUserRole'; import { supabase } from '@/integrations/supabase/client'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; interface ItemDisponivel { id: string; marca: string; descricao: string; tipo: 'peca' | 'componente'; quantidade_disponivel: number; processo_atual_permitido: number; } interface SeletorItensOtimizadoProps { pecasDisponiveis?: ItemDisponivel[]; componentesDisponiveis?: ItemDisponivel[]; itemSelecionado?: ItemDisponivel | null; onItemSelect?: (item: ItemDisponivel) => void; onBatchSelect?: (items: ItemDisponivel[], tipo: 'peca' | 'componente') => Promise; loading?: boolean; onSelectPeca?: (peca: PecaWithComponents) => void; onSelectComponente?: (componente: any) => void; pecaId?: string | null; } interface PecaWithComponents extends Peca { componentes?: any[]; } export const SeletorItensOtimizado: React.FC = ({ pecasDisponiveis = [], componentesDisponiveis = [], itemSelecionado, onItemSelect, onBatchSelect, loading = false, onSelectPeca, onSelectComponente, pecaId }) => { const [searchTerm, setSearchTerm] = useState(''); const [filtroNumeroPeca, setFiltroNumeroPeca] = useState(''); const debouncedSearchTerm = useDebounce(searchTerm, 300); const [pecasFiltradas, setPecasFiltradas] = useState([]); const [loadingPecas, setLoadingPecas] = useState(false); const [loadingComponentes, setLoadingComponentes] = useState(false); const [componentes, setComponentes] = useState([]); const [showComponentes, setShowComponentes] = useState(false); const inputRef = useRef(null); // Estados para funcionalidade administrativa const [showAdminModal, setShowAdminModal] = useState(false); const [selectedPecaForAdmin, setSelectedPecaForAdmin] = useState(null); const [apontamentosPeca, setApontamentosPeca] = useState([]); const [loadingApontamentos, setLoadingApontamentos] = useState(false); const { isAdmin } = useUserRole(); const { fetchComponentesPeca } = useComponentesPeca(); const pecasOrdenadas = useMemo(() => { let pecasFiltradas = pecasDisponiveis; if (filtroNumeroPeca) { pecasFiltradas = pecasDisponiveis.filter(peca => peca.marca.toLowerCase().includes(filtroNumeroPeca.toLowerCase()) ); } return pecasFiltradas.sort((a, b) => a.marca.localeCompare(b.marca)); }, [pecasDisponiveis, filtroNumeroPeca]); const componentesOrdenados = useMemo(() => { return componentesDisponiveis.sort((a, b) => a.marca.localeCompare(b.marca)); }, [componentesDisponiveis]); const fetchPecas = useCallback(async (term: string) => { if (!term.trim()) { setPecasFiltradas([]); return; } try { setLoadingPecas(true); // Implementar busca de peças aqui } catch (error) { console.error('Erro ao buscar peças:', error); } finally { setLoadingPecas(false); } }, []); useEffect(() => { if (onSelectPeca) { fetchPecas(debouncedSearchTerm); } }, [debouncedSearchTerm, fetchPecas, onSelectPeca]); useEffect(() => { if (pecaId && onSelectComponente) { loadComponentes(pecaId); } }, [pecaId, onSelectComponente]); const loadComponentes = useCallback(async (pecaId: string) => { try { setLoadingComponentes(true); const componentesData = await fetchComponentesPeca(pecaId); setComponentes(componentesData || []); setShowComponentes(true); } catch (error) { console.error('Erro ao carregar componentes:', error); toast.error('Erro ao carregar componentes da peça'); } finally { setLoadingComponentes(false); } }, [fetchComponentesPeca]); const handlePecaSelect = useCallback((peca: PecaWithComponents) => { if (onSelectPeca) { onSelectPeca(peca); } else if (onItemSelect) { const itemDisponivel: ItemDisponivel = { id: peca.id, marca: peca.marca, descricao: peca.descricao || '', tipo: 'peca', quantidade_disponivel: peca.quantidadeDisponivel || 0, processo_atual_permitido: (peca as any).processo_atual_permitido || 0 }; onItemSelect(itemDisponivel); } }, [onSelectPeca, onItemSelect]); const handleComponenteSelect = useCallback((componente: any) => { if (onSelectComponente) { onSelectComponente(componente); } }, [onSelectComponente]); const handleItemSelect = useCallback((item: ItemDisponivel) => { if (onItemSelect) { onItemSelect(item); } }, [onItemSelect]); const handleBatchApontamento = useCallback(async (tipo: 'peca' | 'componente') => { if (!onBatchSelect) return; try { const items = tipo === 'peca' ? pecasOrdenadas : componentesOrdenados; await onBatchSelect(items, tipo); } catch (error) { console.error('Erro no apontamento em lote:', error); toast.error('Erro ao realizar apontamento em lote'); } }, [onBatchSelect, pecasOrdenadas, componentesOrdenados]); const getPrioridadeColor = (prioridade: string) => { switch (prioridade?.toLowerCase()) { case 'alta': return 'text-red-400'; case 'média': return 'text-yellow-400'; case 'baixa': return 'text-green-400'; default: return 'text-slate-400'; } }; const PecaItem = ({ peca, onSelect }: { peca: PecaWithComponents; onSelect: (peca: PecaWithComponents) => void }) => { return (
onSelect(peca)}>
{peca.marca}
Prioridade: {peca.prioridade || 'N/A'}
{peca.descricao && (
{peca.descricao}
)}
Qtd Disponível: {peca.quantidadeDisponivel || 0}
); }; const ComponenteItem = ({ componente }: { componente: any }) => (
handleComponenteSelect(componente)} >
{componente.marca_componente}
Perfil: {componente.perfil || 'N/A'}
Peso Unitário: {componente.peso_unitario || 0}kg | Qtd por Peça: {componente.quantidade_por_peca || 1}
{componente.descricao && (
{componente.descricao}
)}
); const ItemDisponivelComponentBase = ({ item, isSelected }: { item: ItemDisponivel; isSelected: boolean }) => { return (
handleItemSelect(item)} >
{item.marca}
{item.descricao}
{/* Botão administrativo - DISPONÍVEL PARA TODAS AS PEÇAS */} {isAdmin && item.tipo === 'peca' && ( )}
Disponível: {item.quantidade_disponivel} Processo: {item.processo_atual_permitido}
); }; const ItemDisponivelComponent = React.memo(({ item, isSelected }: { item: ItemDisponivel; isSelected: boolean }) => (
handleItemSelect(item)} >
{item.marca}
{item.quantidade_disponivel} disponível
{item.descricao && (
{item.descricao}
)}
Processo: {item.processo_atual_permitido}
{isAdmin && ( )}
)); if (onSelectPeca) { return (
setSearchTerm(e.target.value)} ref={inputRef} className="bg-slate-800 border-slate-700 text-slate-300 placeholder-slate-500 shadow-none focus-visible:ring-slate-600 h-9" />
{loadingPecas ? (
Carregando peças...
) : (
{pecasFiltradas.map((peca) => ( ))} {pecasFiltradas.length === 0 && (
Nenhuma peça encontrada.
)}
)} {showComponentes && (

Componentes da Peça

{loadingComponentes ? (
Carregando componentes...
) : (
{componentes.map((componente) => ( ))} {componentes.length === 0 && (
Nenhum componente cadastrado para esta peça.
)}
)}
)}
); } return ( <>
{loading ? (
Carregando itens disponíveis...
) : ( <> {/* Seção de Peças Disponíveis */} {pecasDisponiveis.length > 0 && (

Peças Disponíveis

setFiltroNumeroPeca(e.target.value)} className="bg-slate-800 border-slate-700 text-slate-300 placeholder-slate-500 h-8 w-48" /> {isAdmin && ( )}
{pecasOrdenadas.map((item) => (
{isAdmin && ( )}
))} {pecasOrdenadas.length === 0 && (
{filtroNumeroPeca ? 'Nenhuma peça encontrada com esse filtro.' : 'Nenhuma peça disponível.'}
)}
)} {/* Seção de Componentes Disponíveis */} {componentesDisponiveis.length > 0 && (

Componentes Disponíveis

{componentesOrdenados.map((item) => ( ))}
)} {/* Mensagem quando não há itens */} {pecasDisponiveis.length === 0 && componentesDisponiveis.length === 0 && (
Nenhum item disponível para este processo.
)} )}
{/* Modal Administrativo */} Ferramenta Administrativa - Forçar Exclusão Verificação de apontamentos e opção de forçar exclusão da peça da exibição atual. {selectedPecaForAdmin && (

Informações da Peça

Marca: {selectedPecaForAdmin.marca}
Descrição: {selectedPecaForAdmin.descricao}
Quantidade Disponível: {selectedPecaForAdmin.quantidade_disponivel}
Processo Atual: {selectedPecaForAdmin.processo_atual_permitido}
{loadingApontamentos ? (
Carregando histórico de apontamentos...
) : (

Histórico de Apontamentos ({apontamentosPeca.length})

{apontamentosPeca.length > 0 ? ( <>
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

{apontamentosPeca.map((apontamento, index) => (
Processo: {apontamento.processos?.nome || 'N/A'}
Quantidade: {apontamento.quantidade_produzida}
Data: {new Date(apontamento.created_at).toLocaleString('pt-BR')}
Usuário: {apontamento.usuario_id}
))}
) : (
✅ Nenhum apontamento encontrado para esta peça. É seguro removê-la da exibição.
)}
)}
)}
); // Função para buscar apontamentos de uma peça específica const buscarApontamentosPeca = useCallback(async (peca: ItemDisponivel) => { setLoadingApontamentos(true); try { const { data, error } = await supabase .from('apontamentos_producao') .select(` id, quantidade_produzida, data_apontamento, created_at, processo:processos_fabricacao(nome, ordem), peca:pecas(marca, of_number) `) .eq('tipo_apontamento', 'peca') .eq('peca_id', peca.id) .order('created_at', { ascending: false }); if (error) { console.error('Erro ao buscar apontamentos da peça:', error); toast.error('Erro ao buscar apontamentos da peça'); return; } setApontamentosPeca(data || []); } catch (error) { console.error('Erro ao buscar apontamentos:', error); toast.error('Erro ao buscar apontamentos'); } finally { setLoadingApontamentos(false); } }, []); // Função para abrir o modal administrativo const handleAdminAction = useCallback(async (peca: ItemDisponivel) => { setSelectedPecaForAdmin(peca); setShowAdminModal(true); await buscarApontamentosPeca(peca); }, [buscarApontamentosPeca]); // Função para forçar exclusão da peça da tela const handleForceRemove = useCallback(async () => { if (!selectedPecaForAdmin) return; try { // Aqui você pode implementar a lógica específica para "excluir" a peça da exibição // Por exemplo, marcar como processada ou adicionar a uma lista de exclusões // Por enquanto, vamos apenas mostrar uma mensagem e fechar o modal toast.success(`Peça ${selectedPecaForAdmin.marca} foi removida da exibição`); // Fechar modal setShowAdminModal(false); setSelectedPecaForAdmin(null); setApontamentosPeca([]); // Aqui você poderia chamar uma função para atualizar a lista de peças disponíveis // ou implementar a lógica específica do seu sistema } catch (error) { console.error('Erro ao remover peça:', error); toast.error('Erro ao remover peça da exibição'); } }, [selectedPecaForAdmin]); {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && (
Atenção!

Esta peça possui {apontamentosPeca.length} apontamento(s) registrado(s). Forçar a exclusão irá removê-la da exibição atual, mas não afetará os dados já salvos.

)} {apontamentosPeca.length > 0 && ( <>
Atenção!

{`${apontamentosPeca.length} apontamento(s) registrado(s) encontrado(s) para esta peça`}

)} `${apontamentosPeca.length} registered appointment(s) found for this piece`; }