Files
tracksteel_app/src/components/apontamento/SeletorItensOtimizado.tsx

1279 lines
51 KiB
TypeScript

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<void>;
loading?: boolean;
onSelectPeca?: (peca: PecaWithComponents) => void;
onSelectComponente?: (componente: any) => void;
pecaId?: string | null;
}
interface PecaWithComponents extends Peca {
componentes?: any[];
}
export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
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<PecaWithComponents[]>([]);
const [loadingPecas, setLoadingPecas] = useState(false);
const [loadingComponentes, setLoadingComponentes] = useState(false);
const [componentes, setComponentes] = useState<any[]>([]);
const [showComponentes, setShowComponentes] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
// Estados para funcionalidade administrativa
const [showAdminModal, setShowAdminModal] = useState(false);
const [selectedPecaForAdmin, setSelectedPecaForAdmin] = useState<ItemDisponivel | null>(null);
const [apontamentosPeca, setApontamentosPeca] = useState<any[]>([]);
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 (
<div className="p-2 border border-slate-600 rounded-md hover:bg-slate-700/50 cursor-pointer transition-colors"
onClick={() => onSelect(peca)}>
<div className="space-y-1">
<div className="font-medium text-sm text-blue-300">{peca.marca}</div>
<div className="text-xs text-slate-400">
Prioridade: <span className={getPrioridadeColor(peca.prioridade)}>{peca.prioridade || 'N/A'}</span>
</div>
{peca.descricao && (
<div className="text-xs text-slate-400 truncate" title={peca.descricao}>
{peca.descricao}
</div>
)}
<div className="text-xs text-green-400">
Qtd Disponível: {peca.quantidadeDisponivel || 0}
</div>
</div>
</div>
);
};
const ComponenteItem = ({ componente }: { componente: any }) => (
<div
className="p-2 border border-slate-600 rounded-md hover:bg-slate-700/50 cursor-pointer transition-colors"
onClick={() => handleComponenteSelect(componente)}
>
<div className="space-y-1">
<div className="font-medium text-sm text-blue-300">{componente.marca_componente}</div>
<div className="text-xs text-slate-400">
Perfil: {componente.perfil || 'N/A'}
</div>
<div className="text-xs text-slate-400">
Peso Unitário: {componente.peso_unitario || 0}kg | Qtd por Peça: {componente.quantidade_por_peca || 1}
</div>
{componente.descricao && (
<div className="text-xs text-slate-400 truncate" title={componente.descricao}>
{componente.descricao}
</div>
)}
</div>
</div>
);
const ItemDisponivelComponentBase = ({ item, isSelected }: { item: ItemDisponivel; isSelected: boolean }) => {
return (
<div
className={`p-3 border rounded-md cursor-pointer transition-colors relative ${
isSelected
? 'border-blue-500 bg-blue-900/20'
: 'border-slate-600 hover:bg-slate-700/50'
}`}
onClick={() => handleItemSelect(item)}
>
<div className="space-y-2">
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="font-medium text-sm text-blue-300">{item.marca}</div>
<div className="text-xs text-slate-400 mt-1">
{item.descricao}
</div>
</div>
{/* Botão administrativo - DISPONÍVEL PARA TODAS AS PEÇAS */}
{isAdmin && item.tipo === 'peca' && (
<Button
size="sm"
variant="ghost"
className="h-6 w-6 p-0 text-orange-400 hover:text-orange-300 hover:bg-orange-900/20 ml-2"
onClick={(e) => {
e.stopPropagation();
handleAdminAction(item);
}}
title="Verificar apontamentos e forçar exclusão"
>
<Settings className="h-3 w-3" />
</Button>
)}
</div>
<div className="flex items-center justify-between text-xs">
<span className="text-green-400 font-bold">
Disponível: {item.quantidade_disponivel}
</span>
<span className="text-slate-400">
Processo: {item.processo_atual_permitido}
</span>
</div>
</div>
</div>
);
};
const ItemDisponivelComponent = React.memo(({ item, isSelected }: { item: ItemDisponivel; isSelected: boolean }) => (
<div className="relative">
<div
className={`p-3 border rounded-md cursor-pointer transition-colors ${
isSelected
? 'border-blue-500 bg-blue-900/20'
: 'border-slate-600 hover:bg-slate-700/50'
}`}
onClick={() => handleItemSelect(item)}
>
<div className="space-y-2">
<div className="flex items-center justify-between">
<div className="font-medium text-sm text-blue-300">{item.marca}</div>
<div className="text-xs text-green-400 font-bold">
{item.quantidade_disponivel} disponível
</div>
</div>
{item.descricao && (
<div className="text-xs text-slate-400 truncate" title={item.descricao}>
{item.descricao}
</div>
)}
<div className="text-xs text-slate-500">
Processo: {item.processo_atual_permitido}
</div>
</div>
</div>
{isAdmin && (
<Button
size="sm"
variant="ghost"
className="absolute top-2 right-2 h-6 w-6 p-0 text-orange-400 hover:text-orange-300 hover:bg-orange-900/20"
onClick={(e) => {
e.stopPropagation();
handleAdminAction(item);
}}
title="Verificar apontamentos e forçar exclusão"
>
<Settings className="h-3 w-3" />
</Button>
)}
</div>
));
if (onSelectPeca) {
return (
<div className="space-y-4">
<div className="relative">
<Input
type="text"
placeholder="Buscar peças por marca, OF ou fase..."
value={searchTerm}
onChange={(e) => 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"
/>
<Search className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-slate-500" />
</div>
{loadingPecas ? (
<div className="text-center text-slate-400">Carregando peças...</div>
) : (
<ScrollArea className="rounded-md border border-slate-700 h-[300px] p-2">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{pecasFiltradas.map((peca) => (
<PecaItem key={peca.id} peca={peca} onSelect={handlePecaSelect} />
))}
{pecasFiltradas.length === 0 && (
<div className="text-center text-slate-400 col-span-full">
Nenhuma peça encontrada.
</div>
)}
</div>
</ScrollArea>
)}
{showComponentes && (
<div className="space-y-2">
<h3 className="text-lg font-semibold text-slate-300">Componentes da Peça</h3>
{loadingComponentes ? (
<div className="text-center text-slate-400">Carregando componentes...</div>
) : (
<ScrollArea className="rounded-md border border-slate-700 h-[200px] p-2">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{componentes.map((componente) => (
<ComponenteItem key={componente.id} componente={componente} />
))}
{componentes.length === 0 && (
<div className="text-center text-slate-400 col-span-full">
Nenhum componente cadastrado para esta peça.
</div>
)}
</div>
</ScrollArea>
)}
</div>
)}
</div>
);
}
return (
<>
<div className="space-y-4">
{loading ? (
<div className="text-center text-slate-400">Carregando itens disponíveis...</div>
) : (
<>
{/* Seção de Peças Disponíveis */}
{pecasDisponiveis.length > 0 && (
<div className="space-y-2">
<div className="flex items-center justify-between flex-wrap gap-2">
<h3 className="text-lg font-semibold text-slate-300 flex items-center gap-2">
<Package className="h-5 w-5" />
Peças Disponíveis
</h3>
<div className="flex items-center gap-2">
<Input
type="text"
placeholder="Filtrar por número da peça..."
value={filtroNumeroPeca}
onChange={(e) => setFiltroNumeroPeca(e.target.value)}
className="bg-slate-800 border-slate-700 text-slate-300 placeholder-slate-500 h-8 w-48"
/>
<Button
size="sm"
variant="outline"
onClick={() => handleBatchApontamento('peca')}
className="text-xs whitespace-nowrap"
disabled={pecasOrdenadas.length === 0}
>
Apontar Todas ({pecasOrdenadas.length})
</Button>
{isAdmin && (
<Button
size="sm"
variant="destructive"
className="text-xs whitespace-nowrap flex items-center gap-1"
title="Ferramenta administrativa para forçar exclusão de peças"
>
<Shield className="h-3 w-3" />
Admin
</Button>
)}
</div>
</div>
<ScrollArea className="rounded-md border border-slate-700 h-[300px] p-2">
<div className="space-y-2">
{pecasOrdenadas.map((item) => (
<div key={item.id} className="relative">
<ItemDisponivelComponent
item={item}
isSelected={itemSelecionado?.id === item.id}
/>
{isAdmin && (
<Button
size="sm"
variant="ghost"
className="absolute top-2 right-2 h-6 w-6 p-0 text-orange-400 hover:text-orange-300 hover:bg-orange-900/20"
onClick={(e) => {
e.stopPropagation();
handleAdminAction(item);
}}
title="Verificar apontamentos e forçar exclusão"
>
<AlertTriangle className="h-3 w-3" />
</Button>
)}
</div>
))}
{pecasOrdenadas.length === 0 && (
<div className="text-center text-slate-400 py-8">
{filtroNumeroPeca ? 'Nenhuma peça encontrada com esse filtro.' : 'Nenhuma peça disponível.'}
</div>
)}
</div>
</ScrollArea>
</div>
)}
{/* Seção de Componentes Disponíveis */}
{componentesDisponiveis.length > 0 && (
<div className="space-y-2">
<div className="flex items-center justify-between">
<h3 className="text-lg font-semibold text-slate-300">Componentes Disponíveis</h3>
<Button
size="sm"
variant="outline"
onClick={() => handleBatchApontamento('componente')}
className="text-xs"
disabled={componentesOrdenados.length === 0}
>
Apontar Todos ({componentesOrdenados.length})
</Button>
</div>
<ScrollArea className="rounded-md border border-slate-700 h-[300px] p-2">
<div className="space-y-2">
{componentesOrdenados.map((item) => (
<ItemDisponivelComponent
key={item.id}
item={item}
isSelected={itemSelecionado?.id === item.id}
/>
))}
</div>
</ScrollArea>
</div>
)}
{/* Mensagem quando não há itens */}
{pecasDisponiveis.length === 0 && componentesDisponiveis.length === 0 && (
<div className="text-center text-slate-400 py-8">
Nenhum item disponível para este processo.
</div>
)}
</>
)}
</div>
{/* Modal Administrativo */}
<Dialog open={showAdminModal} onOpenChange={setShowAdminModal}>
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Shield className="h-5 w-5 text-orange-400" />
Ferramenta Administrativa - Forçar Exclusão
</DialogTitle>
<DialogDescription>
Verificação de apontamentos e opção de forçar exclusão da peça da exibição atual.
</DialogDescription>
</DialogHeader>
{selectedPecaForAdmin && (
<div className="space-y-4">
<div className="bg-slate-800 p-4 rounded-lg">
<h4 className="font-semibold text-slate-300 mb-2">Informações da Peça</h4>
<div className="space-y-1 text-sm">
<div><span className="text-slate-400">Marca:</span> <span className="text-slate-200">{selectedPecaForAdmin.marca}</span></div>
<div><span className="text-slate-400">Descrição:</span> <span className="text-slate-200">{selectedPecaForAdmin.descricao}</span></div>
<div><span className="text-slate-400">Quantidade Disponível:</span> <span className="text-green-400 font-bold">{selectedPecaForAdmin.quantidade_disponivel}</span></div>
<div><span className="text-slate-400">Processo Atual:</span> <span className="text-blue-400">{selectedPecaForAdmin.processo_atual_permitido}</span></div>
</div>
</div>
{loadingApontamentos ? (
<div className="text-center text-slate-400 py-4">
Carregando histórico de apontamentos...
</div>
) : (
<div className="space-y-3">
<h4 className="font-semibold text-slate-300">Histórico de Apontamentos ({apontamentosPeca.length})</h4>
{apontamentosPeca.length > 0 ? (
<>
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
<ScrollArea className="h-[200px] border border-slate-700 rounded-lg p-3">
<div className="space-y-2">
{apontamentosPeca.map((apontamento, index) => (
<div key={apontamento.id || index} className="bg-slate-800 p-3 rounded border border-slate-600">
<div className="grid grid-cols-2 gap-2 text-sm">
<div><span className="text-slate-400">Processo:</span> <span className="text-blue-300">{apontamento.processos?.nome || 'N/A'}</span></div>
<div><span className="text-slate-400">Quantidade:</span> <span className="text-green-400">{apontamento.quantidade_produzida}</span></div>
<div><span className="text-slate-400">Data:</span> <span className="text-slate-300">{new Date(apontamento.created_at).toLocaleString('pt-BR')}</span></div>
<div><span className="text-slate-400">Usuário:</span> <span className="text-slate-300">{apontamento.usuario_id}</span></div>
</div>
</div>
))}
</div>
</ScrollArea>
</>
) : (
<div className="bg-green-900/20 border border-green-700 p-4 rounded-lg">
<div className="text-green-300 text-sm">
Nenhum apontamento encontrado para esta peça. É seguro removê-la da exibição.
</div>
</div>
)}
</div>
)}
</div>
)}
<DialogFooter>
<Button
variant="outline"
onClick={() => {
setShowAdminModal(false);
setSelectedPecaForAdmin(null);
setApontamentosPeca([]);
}}
>
Cancelar
</Button>
<Button
variant="destructive"
onClick={() => handleForceRemove()}
disabled={loadingApontamentos}
>
Forçar Exclusão
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
// 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 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div>
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
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 salvos.
</p>
</div>
</div>
</div>
)}
{apontamentosPeca.length > 0 && (
<>
<div className="bg-orange-900/20 border border-orange-700 p-4 rounded-lg">
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 text-orange-400 mt-0.5" />
<div className="space-y-2">
<h5 className="font-semibold text-orange-300">Atenção!</h5>
<p className="text-sm text-orange-200 mt-1">
{`${apontamentosPeca.length} apontamento(s) registrado(s) encontrado(s) para esta peça`}
</p>
</div>
</div>
</div>
</>
)}
`${apontamentosPeca.length} registered appointment(s) found for this piece`;
}