fix(apontamento): isolar estado de quantidade no card para evitar perda de foco ao digitar
This commit is contained in:
@@ -67,6 +67,257 @@ interface PecaWithComponents extends Peca {
|
||||
processo_atual_permitido?: number;
|
||||
}
|
||||
|
||||
const getPrioridadeColor = (prioridade?: string) => {
|
||||
switch (prioridade?.toLowerCase()) {
|
||||
case 'alta': return 'text-red-600 dark:text-red-400';
|
||||
case 'média': return 'text-amber-600 dark:text-yellow-400';
|
||||
case 'baixa': return 'text-emerald-600 dark:text-green-400';
|
||||
default: return 'text-muted-foreground';
|
||||
}
|
||||
};
|
||||
|
||||
const PecaItem = React.memo(({ peca, onSelect }: { peca: PecaWithComponents; onSelect: (peca: PecaWithComponents) => void }) => {
|
||||
return (
|
||||
<div
|
||||
className="p-2 border border-border bg-card hover:bg-accent/50 rounded-md cursor-pointer transition-colors"
|
||||
onClick={() => onSelect(peca)}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<div className="font-semibold text-sm text-foreground">{peca.marca}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Prioridade: <span className={getPrioridadeColor(peca.prioridade)}>{peca.prioridade || 'N/A'}</span>
|
||||
</div>
|
||||
{peca.descricao && (
|
||||
<div className="text-xs text-muted-foreground truncate" title={peca.descricao}>
|
||||
{peca.descricao}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xs font-bold text-emerald-600 dark:text-emerald-400">
|
||||
Qtd Disponível: {peca.quantidadeDisponivel || 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
PecaItem.displayName = 'PecaItem';
|
||||
|
||||
const ComponenteItem = React.memo(({ componente, onSelect }: { componente: ComponenteItemData; onSelect: (componente: ComponenteItemData) => void }) => (
|
||||
<div
|
||||
className="p-2 border border-border bg-card hover:bg-accent/50 rounded-md cursor-pointer transition-colors"
|
||||
onClick={() => onSelect(componente)}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<div className="font-semibold text-sm text-foreground">{componente.marca_componente}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Perfil: {componente.perfil || 'N/A'}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
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-muted-foreground truncate" title={componente.descricao}>
|
||||
{componente.descricao}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
ComponenteItem.displayName = 'ComponenteItem';
|
||||
|
||||
interface ItemDisponivelCardProps {
|
||||
item: ItemDisponivel;
|
||||
isSelected: boolean;
|
||||
isAdmin?: boolean;
|
||||
onSelect?: (item: ItemDisponivel) => void;
|
||||
onAdminAction?: (item: ItemDisponivel) => void;
|
||||
onApontarItemDireto?: (item: ItemDisponivel, quantidade: number) => Promise<boolean>;
|
||||
}
|
||||
|
||||
const ItemDisponivelCard = React.memo(({
|
||||
item,
|
||||
isSelected,
|
||||
isAdmin,
|
||||
onSelect,
|
||||
onAdminAction,
|
||||
onApontarItemDireto,
|
||||
}: ItemDisponivelCardProps) => {
|
||||
const [qtdValue, setQtdValue] = useState<string>('');
|
||||
const [isTodas, setIsTodas] = useState<boolean>(false);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
// Mantém sincronizado se a quantidade disponível mudar ou modo 'todas' estiver ativo
|
||||
useEffect(() => {
|
||||
if (isTodas) {
|
||||
setQtdValue(item.quantidade_disponivel.toString());
|
||||
} else if (qtdValue) {
|
||||
const parsed = parseInt(qtdValue, 10);
|
||||
if (!isNaN(parsed) && parsed > item.quantidade_disponivel) {
|
||||
setQtdValue(item.quantidade_disponivel.toString());
|
||||
}
|
||||
}
|
||||
}, [item.quantidade_disponivel, isTodas]);
|
||||
|
||||
const handleToggleTodas = () => {
|
||||
setIsTodas((prev) => {
|
||||
const novo = !prev;
|
||||
setQtdValue(novo ? item.quantidade_disponivel.toString() : '');
|
||||
return novo;
|
||||
});
|
||||
};
|
||||
|
||||
const handleQtdChange = (val: string) => {
|
||||
setQtdValue(val);
|
||||
if (isTodas) {
|
||||
setIsTodas(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleExecutarBaixa = async () => {
|
||||
if (!onApontarItemDireto || isLoading) return;
|
||||
const quantidade = isTodas ? item.quantidade_disponivel : parseInt(qtdValue, 10);
|
||||
|
||||
if (isNaN(quantidade) || quantidade <= 0) {
|
||||
toast.error(`Informe a quantidade para ${item.marca} ou ative 'Todas'`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quantidade > item.quantidade_disponivel) {
|
||||
toast.error(`Quantidade não pode ser maior que ${item.quantidade_disponivel} disponível`);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const sucesso = await onApontarItemDireto(item, quantidade);
|
||||
if (sucesso) {
|
||||
setQtdValue('');
|
||||
setIsTodas(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao executar baixa direta:', error);
|
||||
toast.error('Erro ao registrar apontamento');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div
|
||||
className={`p-3 border rounded-md transition-colors ${
|
||||
isSelected
|
||||
? 'border-primary bg-primary/10 ring-1 ring-primary'
|
||||
: 'border-border bg-card hover:bg-accent/40'
|
||||
}`}
|
||||
onClick={() => onSelect?.(item)}
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="font-semibold text-sm text-foreground flex items-center gap-2">
|
||||
<span>{item.marca}</span>
|
||||
{item.perfil && (
|
||||
<span className="text-xs px-1.5 py-0.5 rounded bg-muted text-muted-foreground font-mono font-normal">
|
||||
{item.perfil}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs font-bold text-emerald-600 dark:text-emerald-400">
|
||||
{item.quantidade_disponivel} disponível
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.descricao && item.descricao !== item.perfil && (
|
||||
<div className="text-xs text-muted-foreground truncate" title={item.descricao}>
|
||||
{item.descricao}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Linha com processo e controles rápidos de apontamento */}
|
||||
<div className="flex items-center justify-between gap-2 pt-1 flex-wrap">
|
||||
<div className="text-xs text-muted-foreground font-medium">
|
||||
Processo: {item.nome_processo || item.processo_atual_permitido}
|
||||
</div>
|
||||
|
||||
{onApontarItemDireto && (
|
||||
<div
|
||||
className="flex items-center gap-1.5 ml-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
min="1"
|
||||
max={item.quantidade_disponivel}
|
||||
placeholder="Quant."
|
||||
value={qtdValue}
|
||||
onChange={(e) => handleQtdChange(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
handleExecutarBaixa();
|
||||
}
|
||||
}}
|
||||
disabled={isTodas || isLoading}
|
||||
className="h-7 w-20 text-xs px-2 text-center font-medium bg-background border-input shadow-none"
|
||||
/>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={isTodas ? "default" : "outline"}
|
||||
onClick={handleToggleTodas}
|
||||
disabled={isLoading}
|
||||
className={`h-7 px-2.5 text-xs font-semibold transition-colors ${
|
||||
isTodas
|
||||
? "bg-emerald-600 hover:bg-emerald-700 text-white border-emerald-600 shadow-sm"
|
||||
: "hover:bg-accent text-foreground"
|
||||
}`}
|
||||
title="Habilitar/desabilitar apontar todas as unidades disponíveis"
|
||||
>
|
||||
Todas
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
disabled={isLoading || (!isTodas && (!qtdValue || parseInt(qtdValue, 10) <= 0))}
|
||||
onClick={handleExecutarBaixa}
|
||||
className="h-7 px-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold text-xs flex items-center gap-1 shadow-sm transition-all"
|
||||
title="Baixar quantidade no apontamento"
|
||||
>
|
||||
{isLoading ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
<span>Baixar</span>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isAdmin && onAdminAction && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="absolute top-2 right-2 h-6 w-6 p-0 text-orange-500 hover:text-orange-600 hover:bg-orange-500/10"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onAdminAction(item);
|
||||
}}
|
||||
title="Verificar apontamentos e forçar exclusão"
|
||||
>
|
||||
<Settings className="h-3 w-3" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
ItemDisponivelCard.displayName = 'ItemDisponivelCard';
|
||||
|
||||
export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
pecasDisponiveis = [],
|
||||
componentesDisponiveis = [],
|
||||
@@ -86,11 +337,6 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
const [loadingPecas, setLoadingPecas] = useState(false);
|
||||
const [loadingComponentes, setLoadingComponentes] = useState(false);
|
||||
const [componentes, setComponentes] = useState<ComponenteItemData[]>([]);
|
||||
|
||||
// Estados locais para apontamento direto por card (quantidade, modo todas e loading)
|
||||
const [qtdCards, setQtdCards] = useState<Record<string, string>>({});
|
||||
const [todasCards, setTodasCards] = useState<Record<string, boolean>>({});
|
||||
const [loadingApontandoId, setLoadingApontandoId] = useState<string | null>(null);
|
||||
const [showComponentes, setShowComponentes] = useState(false);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -184,59 +430,6 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
return comps.sort((a, b) => a.marca.localeCompare(b.marca, undefined, { numeric: true, sensitivity: 'base' }));
|
||||
}, [componentesDisponiveis, filtroNumeroPeca]);
|
||||
|
||||
const handleQtdCardChange = useCallback((itemId: string, value: string) => {
|
||||
setQtdCards(prev => ({ ...prev, [itemId]: value }));
|
||||
setTodasCards(prev => ({ ...prev, [itemId]: false }));
|
||||
}, []);
|
||||
|
||||
const handleToggleTodas = useCallback((itemId: string, qtdDisponivel: number) => {
|
||||
setTodasCards(prev => {
|
||||
const novoEstado = !prev[itemId];
|
||||
if (novoEstado) {
|
||||
setQtdCards(q => ({ ...q, [itemId]: qtdDisponivel.toString() }));
|
||||
} else {
|
||||
setQtdCards(q => ({ ...q, [itemId]: '' }));
|
||||
}
|
||||
return { ...prev, [itemId]: novoEstado };
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleExecutarBaixa = useCallback(async (item: ItemDisponivel) => {
|
||||
if (!onApontarItemDireto) return;
|
||||
const isTodas = todasCards[item.id];
|
||||
const qtdDigitada = qtdCards[item.id];
|
||||
const quantidade = isTodas ? item.quantidade_disponivel : parseInt(qtdDigitada);
|
||||
|
||||
if (isNaN(quantidade) || quantidade <= 0) {
|
||||
toast.error(`Informe a quantidade para ${item.marca} ou ative 'Todas'`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quantidade > item.quantidade_disponivel) {
|
||||
toast.error(`Quantidade não pode ser maior que ${item.quantidade_disponivel} disponível`);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoadingApontandoId(item.id);
|
||||
try {
|
||||
const sucesso = await onApontarItemDireto(item, quantidade);
|
||||
if (sucesso) {
|
||||
setQtdCards(prev => {
|
||||
const copia = { ...prev };
|
||||
delete copia[item.id];
|
||||
return copia;
|
||||
});
|
||||
setTodasCards(prev => {
|
||||
const copia = { ...prev };
|
||||
delete copia[item.id];
|
||||
return copia;
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setLoadingApontandoId(null);
|
||||
}
|
||||
}, [onApontarItemDireto, todasCards, qtdCards]);
|
||||
|
||||
const fetchPecas = useCallback(async (term: string) => {
|
||||
if (!term.trim()) {
|
||||
setPecasFiltradas([]);
|
||||
@@ -318,174 +511,6 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
}
|
||||
}, [onBatchSelect, pecasOrdenadas, componentesOrdenados]);
|
||||
|
||||
const getPrioridadeColor = (prioridade: string) => {
|
||||
switch (prioridade?.toLowerCase()) {
|
||||
case 'alta': return 'text-red-600 dark:text-red-400';
|
||||
case 'média': return 'text-amber-600 dark:text-yellow-400';
|
||||
case 'baixa': return 'text-emerald-600 dark:text-green-400';
|
||||
default: return 'text-muted-foreground';
|
||||
}
|
||||
};
|
||||
|
||||
const PecaItem = ({ peca, onSelect }: { peca: PecaWithComponents; onSelect: (peca: PecaWithComponents) => void }) => {
|
||||
return (
|
||||
<div className="p-2 border border-border bg-card hover:bg-accent/50 rounded-md cursor-pointer transition-colors"
|
||||
onClick={() => onSelect(peca)}>
|
||||
<div className="space-y-1">
|
||||
<div className="font-semibold text-sm text-foreground">{peca.marca}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Prioridade: <span className={getPrioridadeColor(peca.prioridade)}>{peca.prioridade || 'N/A'}</span>
|
||||
</div>
|
||||
{peca.descricao && (
|
||||
<div className="text-xs text-muted-foreground truncate" title={peca.descricao}>
|
||||
{peca.descricao}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-xs font-bold text-emerald-600 dark:text-emerald-400">
|
||||
Qtd Disponível: {peca.quantidadeDisponivel || 0}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ComponenteItem = ({ componente }: { componente: ComponenteItemData }) => (
|
||||
<div
|
||||
className="p-2 border border-border bg-card hover:bg-accent/50 rounded-md cursor-pointer transition-colors"
|
||||
onClick={() => handleComponenteSelect(componente)}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<div className="font-semibold text-sm text-foreground">{componente.marca_componente}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Perfil: {componente.perfil || 'N/A'}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
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-muted-foreground truncate" title={componente.descricao}>
|
||||
{componente.descricao}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ItemDisponivelComponent = ({ item, isSelected }: { item: ItemDisponivel; isSelected: boolean }) => {
|
||||
const isTodas = Boolean(todasCards[item.id]);
|
||||
const qtdValue = qtdCards[item.id] ?? (isTodas ? item.quantidade_disponivel.toString() : '');
|
||||
const isLoading = loadingApontandoId === item.id;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div
|
||||
className={`p-3 border rounded-md transition-colors ${
|
||||
isSelected
|
||||
? 'border-primary bg-primary/10 ring-1 ring-primary'
|
||||
: 'border-border bg-card hover:bg-accent/40'
|
||||
}`}
|
||||
onClick={() => handleItemSelect(item)}
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="font-semibold text-sm text-foreground flex items-center gap-2">
|
||||
<span>{item.marca}</span>
|
||||
{item.perfil && (
|
||||
<span className="text-xs px-1.5 py-0.5 rounded bg-muted text-muted-foreground font-mono font-normal">
|
||||
{item.perfil}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs font-bold text-emerald-600 dark:text-emerald-400">
|
||||
{item.quantidade_disponivel} disponível
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.descricao && item.descricao !== item.perfil && (
|
||||
<div className="text-xs text-muted-foreground truncate" title={item.descricao}>
|
||||
{item.descricao}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Linha com processo e controles rápidos de apontamento desenhados pelo usuário */}
|
||||
<div className="flex items-center justify-between gap-2 pt-1 flex-wrap">
|
||||
<div className="text-xs text-muted-foreground font-medium">
|
||||
Processo: {item.nome_processo || item.processo_atual_permitido}
|
||||
</div>
|
||||
|
||||
{onApontarItemDireto && (
|
||||
<div
|
||||
className="flex items-center gap-1.5 ml-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
min="1"
|
||||
max={item.quantidade_disponivel}
|
||||
placeholder="Quant."
|
||||
value={qtdValue}
|
||||
onChange={(e) => handleQtdCardChange(item.id, e.target.value)}
|
||||
disabled={isTodas || isLoading}
|
||||
className="h-7 w-20 text-xs px-2 text-center font-medium bg-background border-input shadow-none"
|
||||
/>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant={isTodas ? "default" : "outline"}
|
||||
onClick={() => handleToggleTodas(item.id, item.quantidade_disponivel)}
|
||||
disabled={isLoading}
|
||||
className={`h-7 px-2.5 text-xs font-semibold transition-colors ${
|
||||
isTodas
|
||||
? "bg-emerald-600 hover:bg-emerald-700 text-white border-emerald-600 shadow-sm"
|
||||
: "hover:bg-accent text-foreground"
|
||||
}`}
|
||||
title="Habilitar/desabilitar apontar todas as unidades disponíveis"
|
||||
>
|
||||
Todas
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
disabled={isLoading || (!isTodas && (!qtdValue || parseInt(qtdValue) <= 0))}
|
||||
onClick={() => handleExecutarBaixa(item)}
|
||||
className="h-7 px-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold text-xs flex items-center gap-1 shadow-sm transition-all"
|
||||
title="Baixar quantidade no apontamento"
|
||||
>
|
||||
{isLoading ? (
|
||||
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
<span>Baixar</span>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isAdmin && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="absolute top-2 right-2 h-6 w-6 p-0 text-orange-500 hover:text-orange-600 hover:bg-orange-500/10"
|
||||
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">
|
||||
@@ -527,7 +552,7 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
<ScrollArea className="rounded-md border border-border 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} />
|
||||
<ComponenteItem key={componente.id} componente={componente} onSelect={handleComponenteSelect} />
|
||||
))}
|
||||
{componentes.length === 0 && (
|
||||
<div className="text-center text-muted-foreground col-span-full">
|
||||
@@ -592,27 +617,15 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
<ScrollArea className="rounded-md border border-border 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-500 hover:text-orange-600 hover:bg-orange-500/10"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleAdminAction(item);
|
||||
}}
|
||||
title="Verificar apontamentos e forçar exclusão"
|
||||
>
|
||||
<AlertTriangle className="h-3 w-3" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<ItemDisponivelCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
isSelected={itemSelecionado?.id === item.id}
|
||||
isAdmin={isAdmin}
|
||||
onSelect={handleItemSelect}
|
||||
onAdminAction={handleAdminAction}
|
||||
onApontarItemDireto={onApontarItemDireto}
|
||||
/>
|
||||
))}
|
||||
{pecasOrdenadas.length === 0 && (
|
||||
<div className="text-center text-muted-foreground py-8">
|
||||
@@ -645,10 +658,14 @@ export const SeletorItensOtimizado: React.FC<SeletorItensOtimizadoProps> = ({
|
||||
<ScrollArea className="rounded-md border border-border h-[300px] p-2">
|
||||
<div className="space-y-2">
|
||||
{componentesOrdenados.map((item) => (
|
||||
<ItemDisponivelComponent
|
||||
<ItemDisponivelCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
isSelected={itemSelecionado?.id === item.id}
|
||||
isAdmin={isAdmin}
|
||||
onSelect={handleItemSelect}
|
||||
onAdminAction={handleAdminAction}
|
||||
onApontarItemDireto={onApontarItemDireto}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user