fix: correcao no carregamento reativo de pecas e componentes no apontamento de producao
This commit is contained in:
@@ -13,7 +13,6 @@ import { usePecas } from '@/hooks/usePecas';
|
|||||||
import { useOFs } from '@/hooks/useOFs';
|
import { useOFs } from '@/hooks/useOFs';
|
||||||
import { useComponentesAgrupados } from '@/hooks/useComponentesAgrupados';
|
import { useComponentesAgrupados } from '@/hooks/useComponentesAgrupados';
|
||||||
import { SeletorItensOtimizado } from './SeletorItensOtimizado';
|
import { SeletorItensOtimizado } from './SeletorItensOtimizado';
|
||||||
import { useApontamentosValidacao } from '@/hooks/useApontamentosValidacao';
|
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
interface ItemDisponivel {
|
interface ItemDisponivel {
|
||||||
@@ -25,7 +24,7 @@ interface ItemDisponivel {
|
|||||||
processo_atual_permitido: number;
|
processo_atual_permitido: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache para manter seleções do usuário
|
// Cache local para manter seleções básicas do formulário
|
||||||
const formCache = {
|
const formCache = {
|
||||||
of_number: '',
|
of_number: '',
|
||||||
fase: '',
|
fase: '',
|
||||||
@@ -33,13 +32,6 @@ const formCache = {
|
|||||||
data_apontamento: new Date().toISOString().split('T')[0]
|
data_apontamento: new Date().toISOString().split('T')[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cache para itens já processados
|
|
||||||
const itensCache = new Map<string, {
|
|
||||||
pecasDisponiveis: ItemDisponivel[];
|
|
||||||
componentesDisponiveis: ItemDisponivel[];
|
|
||||||
timestamp: number;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
export const ApontamentoForm = () => {
|
export const ApontamentoForm = () => {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
of_number: formCache.of_number || '',
|
of_number: formCache.of_number || '',
|
||||||
@@ -52,55 +44,40 @@ export const ApontamentoForm = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [itemSelecionado, setItemSelecionado] = useState<ItemDisponivel | null>(null);
|
const [itemSelecionado, setItemSelecionado] = useState<ItemDisponivel | null>(null);
|
||||||
const [itensDisponiveis, setItensDisponiveis] = useState<{
|
|
||||||
pecasDisponiveis: ItemDisponivel[];
|
|
||||||
componentesDisponiveis: ItemDisponivel[];
|
|
||||||
}>({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
const [cacheValido, setCacheValido] = useState(false);
|
const [cacheValido, setCacheValido] = useState(false);
|
||||||
const [loadingItens, setLoadingItens] = useState(false);
|
|
||||||
const [isProcessingItems, setIsProcessingItems] = useState(false);
|
|
||||||
|
|
||||||
const { criarApontamento, refetch, processos } = useApontamentosProducao();
|
const { criarApontamento, refetch, processos, apontamentos, loading: loadingApontamentos } = useApontamentosProducao();
|
||||||
const { pecas } = usePecas();
|
const { pecas, loading: loadingPecas } = usePecas();
|
||||||
const { ofs } = useOFs();
|
const { ofs } = useOFs();
|
||||||
const { componentesAgrupados } = useComponentesAgrupados(formData.of_number, formData.fase);
|
const { componentesAgrupados, loading: loadingComponentes } = useComponentesAgrupados(formData.of_number, formData.fase, pecas);
|
||||||
const {
|
|
||||||
validarSequenciaProcessos,
|
|
||||||
precarregarDados,
|
|
||||||
limparCache: limparCacheValidacao
|
|
||||||
} = useApontamentosValidacao();
|
|
||||||
|
|
||||||
// Buscar fases únicas da OF selecionada
|
// Buscar fases únicas da OF selecionada
|
||||||
const fasesDisponiveis = useMemo(() =>
|
const fasesDisponiveis = useMemo(() => {
|
||||||
|
if (!formData.of_number || !pecas.length) return [];
|
||||||
|
return Array.from(
|
||||||
|
new Set(
|
||||||
pecas
|
pecas
|
||||||
.filter(peca => peca.of_number === formData.of_number)
|
.filter(peca => peca.of_number === formData.of_number)
|
||||||
.map(peca => peca.etapa_fase)
|
.map(peca => peca.etapa_fase)
|
||||||
.filter((fase, index, array) => fase && array.indexOf(fase) === index)
|
.filter(Boolean)
|
||||||
.sort(),
|
)
|
||||||
[pecas, formData.of_number]
|
).sort();
|
||||||
);
|
}, [pecas, formData.of_number]);
|
||||||
|
|
||||||
// Peças filtradas - memoizado para evite recálculos
|
// Processo selecionado atualmente
|
||||||
const filteredPecas = useMemo(() =>
|
const processoSelecionado = useMemo(() => {
|
||||||
pecas.filter(peca =>
|
return processos.find(p => p.id === formData.processo_id) || null;
|
||||||
peca.of_number === formData.of_number &&
|
}, [processos, formData.processo_id]);
|
||||||
peca.etapa_fase === formData.fase &&
|
|
||||||
!peca.tem_componentes
|
|
||||||
),
|
|
||||||
[pecas, formData.of_number, formData.fase]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Chave única para cache
|
|
||||||
const cacheKey = useMemo(() =>
|
|
||||||
`${formData.of_number}_${formData.fase}_${formData.processo_id}`,
|
|
||||||
[formData.of_number, formData.fase, formData.processo_id]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Salvar cache quando seleções básicas mudam
|
// Salvar cache quando seleções básicas mudam
|
||||||
const updateCache = useCallback((updates: Partial<typeof formData>) => {
|
const updateCache = useCallback((updates: Partial<typeof formData>) => {
|
||||||
Object.assign(formCache, updates);
|
Object.assign(formCache, updates);
|
||||||
|
try {
|
||||||
localStorage.setItem('apontamento_cache', JSON.stringify(formCache));
|
localStorage.setItem('apontamento_cache', JSON.stringify(formCache));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Erro ao salvar cache:', e);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Carregar cache inicial
|
// Carregar cache inicial
|
||||||
@@ -124,120 +101,87 @@ export const ApontamentoForm = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Função para processar itens com cache
|
// Cálculo reativo de peças e componentes disponíveis para o processo selecionado
|
||||||
const processarItensDisponiveis = useCallback(async () => {
|
const itensDisponiveis = useMemo(() => {
|
||||||
const { of_number, fase, processo_id } = formData;
|
const { of_number, fase, processo_id } = formData;
|
||||||
|
|
||||||
if (!of_number || !fase || !processo_id) {
|
if (!of_number || !fase || !processo_id || !pecas.length) {
|
||||||
console.log('⚠️ Campos obrigatórios faltando para carregar itens');
|
return { pecasDisponiveis: [], componentesDisponiveis: [] };
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verificar se já temos no cache (válido por 30 segundos)
|
const ordemProcesso = processoSelecionado?.ordem || 1;
|
||||||
const cached = itensCache.get(cacheKey);
|
|
||||||
const now = Date.now();
|
|
||||||
if (cached && (now - cached.timestamp) < 30000) {
|
|
||||||
console.log('📦 Usando itens do cache');
|
|
||||||
setItensDisponiveis(cached);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aguardar dados das peças e componentes
|
// 1. Peças da OF e Fase selecionadas
|
||||||
if (filteredPecas.length === 0 && componentesAgrupados.length === 0) {
|
const pecasDaFase = pecas.filter(
|
||||||
console.log('⏳ Aguardando dados de peças e componentes...');
|
p => p.of_number === of_number && p.etapa_fase === fase
|
||||||
return;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (isProcessingItems) {
|
const pecasDisponiveis: ItemDisponivel[] = [];
|
||||||
console.log('🔄 Já processando itens, aguardando...');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n🚀 === PROCESSANDO ITENS COM CACHE ===');
|
pecasDaFase.forEach(peca => {
|
||||||
console.log(`📋 OF: ${of_number}, Fase: ${fase}, Processo: ${processo_id}`);
|
// Calcular quanto já foi apontado desta peça neste processo
|
||||||
|
const totalApontado = apontamentos
|
||||||
|
.filter(a => a.tipo_apontamento === 'peca' && a.peca_id === peca.id && a.processo_id === processo_id)
|
||||||
|
.reduce((sum, a) => sum + (Number(a.quantidade_produzida) || 0), 0);
|
||||||
|
|
||||||
setIsProcessingItems(true);
|
const saldoDisponivel = Math.max(0, (Number(peca.quantidade) || 0) - totalApontado);
|
||||||
setLoadingItens(true);
|
|
||||||
|
|
||||||
try {
|
if (saldoDisponivel > 0) {
|
||||||
// Calcular itens disponíveis baseado nos dados existentes
|
pecasDisponiveis.push({
|
||||||
console.log('🧮 Calculando itens disponíveis...');
|
|
||||||
const itens = {
|
|
||||||
pecasDisponiveis: filteredPecas.map(peca => ({
|
|
||||||
id: peca.id,
|
id: peca.id,
|
||||||
marca: peca.marca,
|
marca: peca.marca,
|
||||||
descricao: peca.descricao,
|
descricao: peca.descricao || '',
|
||||||
tipo: 'peca' as const,
|
tipo: 'peca',
|
||||||
quantidade_disponivel: peca.quantidade,
|
quantidade_disponivel: saldoDisponivel,
|
||||||
processo_atual_permitido: 1
|
processo_atual_permitido: ordemProcesso
|
||||||
})),
|
});
|
||||||
componentesDisponiveis: componentesAgrupados.map(comp => ({
|
}
|
||||||
id: comp.componente_ids[0] || '', // Use primeiro ID do array
|
});
|
||||||
|
|
||||||
|
// 2. Componentes da OF e Fase selecionadas
|
||||||
|
const componentesDisponiveis: ItemDisponivel[] = [];
|
||||||
|
|
||||||
|
if (componentesAgrupados && componentesAgrupados.length > 0) {
|
||||||
|
componentesAgrupados.forEach(comp => {
|
||||||
|
// Calcular quanto já foi apontado deste componente neste processo
|
||||||
|
const totalApontadoComp = apontamentos
|
||||||
|
.filter(a => a.tipo_apontamento === 'componente' && comp.componente_ids.includes(a.componente_id || '') && a.processo_id === processo_id)
|
||||||
|
.reduce((sum, a) => sum + (Number(a.quantidade_produzida) || 0), 0);
|
||||||
|
|
||||||
|
const saldoComp = Math.max(0, (Number(comp.quantidade_total) || 0) - totalApontadoComp);
|
||||||
|
|
||||||
|
if (saldoComp > 0) {
|
||||||
|
componentesDisponiveis.push({
|
||||||
|
id: comp.componente_ids[0] || '',
|
||||||
marca: comp.marca_componente,
|
marca: comp.marca_componente,
|
||||||
descricao: comp.descricao || '',
|
descricao: comp.descricao || comp.perfil || '',
|
||||||
tipo: 'componente' as const,
|
tipo: 'componente',
|
||||||
quantidade_disponivel: comp.quantidade_total,
|
quantidade_disponivel: saldoComp,
|
||||||
processo_atual_permitido: 1
|
processo_atual_permitido: ordemProcesso
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('✅ Itens calculados:', {
|
|
||||||
pecas: itens.pecasDisponiveis.length,
|
|
||||||
componentes: itens.componentesDisponiveis.length
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
// 4. Salvar no cache
|
|
||||||
itensCache.set(cacheKey, {
|
|
||||||
...itens,
|
|
||||||
timestamp: now
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 5. Atualizar estado
|
|
||||||
setItensDisponiveis(itens);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Erro ao processar itens:', error);
|
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
} finally {
|
|
||||||
setLoadingItens(false);
|
|
||||||
setIsProcessingItems(false);
|
|
||||||
}
|
}
|
||||||
}, [
|
|
||||||
formData.of_number,
|
|
||||||
formData.fase,
|
|
||||||
formData.processo_id
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Callback para atualizar dados
|
return { pecasDisponiveis, componentesDisponiveis };
|
||||||
const updateData = useCallback(() => {
|
}, [formData.of_number, formData.fase, formData.processo_id, pecas, apontamentos, processoSelecionado, componentesAgrupados]);
|
||||||
// 4. Atualizar dados para nova seleção
|
|
||||||
console.log('✅ Dados atualizados para nova seleção de OF/processo');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Efeito controlado para carregar itens
|
// Sincronizar item selecionado caso não exista mais na lista disponível
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (formData.of_number && formData.fase && formData.processo_id) {
|
if (itemSelecionado) {
|
||||||
// Usar timeout para evitar chamadas excessivas
|
const listaAtual = itemSelecionado.tipo === 'peca'
|
||||||
const timeoutId = setTimeout(() => {
|
? itensDisponiveis.pecasDisponiveis
|
||||||
processarItensDisponiveis();
|
: itensDisponiveis.componentesDisponiveis;
|
||||||
}, 300);
|
|
||||||
|
|
||||||
return () => clearTimeout(timeoutId);
|
const itemAindaExiste = listaAtual.find(i => i.id === itemSelecionado.id);
|
||||||
} else {
|
if (!itemAindaExiste) {
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
}
|
|
||||||
}, [formData.of_number, formData.fase, formData.processo_id]);
|
|
||||||
|
|
||||||
// Reset do item selecionado quando dados mudam
|
|
||||||
useEffect(() => {
|
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setFormData(prev => ({
|
setFormData(prev => ({ ...prev, quantidade_produzida: '', todas_disponiveis: false }));
|
||||||
...prev,
|
} else if (itemAindaExiste.quantidade_disponivel !== itemSelecionado.quantidade_disponivel) {
|
||||||
quantidade_produzida: '',
|
setItemSelecionado(itemAindaExiste);
|
||||||
todas_disponiveis: false
|
}
|
||||||
}));
|
}
|
||||||
}, [formData.of_number, formData.fase, formData.processo_id]);
|
}, [itensDisponiveis, itemSelecionado]);
|
||||||
|
|
||||||
// Auto-preenchimento da quantidade quando "todas disponíveis" é marcado
|
// Auto-preenchimento da quantidade quando "todas disponíveis" é marcado
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -259,9 +203,9 @@ export const ApontamentoForm = () => {
|
|||||||
const tipoTexto = tipo === 'peca' ? 'peças' : 'componentes';
|
const tipoTexto = tipo === 'peca' ? 'peças' : 'componentes';
|
||||||
|
|
||||||
const confirmacao = window.confirm(
|
const confirmacao = window.confirm(
|
||||||
`Deseja registrar ${totalItens} ${tipoTexto} com suas respectivas quantidades totais?\n\n` +
|
`Deseja registrar ${totalItens} ${tipoTexto} com suas respectivas quantidades totais disponíveis?\n\n` +
|
||||||
`Total de itens: ${totalItens}\n` +
|
`Total de itens: ${totalItens}\n` +
|
||||||
`Processo: ${formData.processo_id || 'N/A'}`
|
`Processo: ${processoSelecionado?.nome || 'N/A'}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!confirmacao) return;
|
if (!confirmacao) return;
|
||||||
@@ -303,11 +247,8 @@ export const ApontamentoForm = () => {
|
|||||||
|
|
||||||
if (sucessos > 0) {
|
if (sucessos > 0) {
|
||||||
toast.success(`${sucessos} ${tipoTexto} registradas com sucesso!${erros > 0 ? ` (${erros} com erro)` : ''}`);
|
toast.success(`${sucessos} ${tipoTexto} registradas com sucesso!${erros > 0 ? ` (${erros} com erro)` : ''}`);
|
||||||
|
await refetch();
|
||||||
await Promise.all([
|
resetFormForNewEntry();
|
||||||
refetch(),
|
|
||||||
resetFormForNewEntry()
|
|
||||||
]);
|
|
||||||
} else {
|
} else {
|
||||||
toast.error(`Erro ao registrar ${tipoTexto} em lote`);
|
toast.error(`Erro ao registrar ${tipoTexto} em lote`);
|
||||||
}
|
}
|
||||||
@@ -331,9 +272,6 @@ export const ApontamentoForm = () => {
|
|||||||
setFormData(prev => ({ ...prev, ...updates }));
|
setFormData(prev => ({ ...prev, ...updates }));
|
||||||
updateCache({ of_number: ofNumber, fase: '', processo_id: '' });
|
updateCache({ of_number: ofNumber, fase: '', processo_id: '' });
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
// Limpar cache relacionado
|
|
||||||
itensCache.clear();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFaseChange = (fase: string) => {
|
const handleFaseChange = (fase: string) => {
|
||||||
@@ -346,9 +284,6 @@ export const ApontamentoForm = () => {
|
|||||||
setFormData(prev => ({ ...prev, ...updates }));
|
setFormData(prev => ({ ...prev, ...updates }));
|
||||||
updateCache({ fase: fase, processo_id: '' });
|
updateCache({ fase: fase, processo_id: '' });
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
// Limpar cache relacionado
|
|
||||||
itensCache.clear();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleProcessoChange = (processoId: string) => {
|
const handleProcessoChange = (processoId: string) => {
|
||||||
@@ -360,7 +295,6 @@ export const ApontamentoForm = () => {
|
|||||||
setFormData(prev => ({ ...prev, ...updates }));
|
setFormData(prev => ({ ...prev, ...updates }));
|
||||||
updateCache({ processo_id: processoId });
|
updateCache({ processo_id: processoId });
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleItemSelect = (item: ItemDisponivel) => {
|
const handleItemSelect = (item: ItemDisponivel) => {
|
||||||
@@ -387,10 +321,7 @@ export const ApontamentoForm = () => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Função para resetar form e atualizar dados
|
const resetFormForNewEntry = () => {
|
||||||
const resetFormForNewEntry = async () => {
|
|
||||||
console.log('🔄 Resetando formulário e limpando cache...');
|
|
||||||
|
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setFormData(prev => ({
|
setFormData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -398,9 +329,6 @@ export const ApontamentoForm = () => {
|
|||||||
observacoes: '',
|
observacoes: '',
|
||||||
todas_disponiveis: false
|
todas_disponiveis: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Limpar cache e forçar recarregamento
|
|
||||||
itensCache.clear();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
@@ -413,7 +341,7 @@ export const ApontamentoForm = () => {
|
|||||||
|
|
||||||
const quantidade = parseInt(formData.quantidade_produzida);
|
const quantidade = parseInt(formData.quantidade_produzida);
|
||||||
|
|
||||||
if (quantidade <= 0 || quantidade > itemSelecionado.quantidade_disponivel) {
|
if (isNaN(quantidade) || quantidade <= 0 || quantidade > itemSelecionado.quantidade_disponivel) {
|
||||||
toast.error('Quantidade inválida');
|
toast.error('Quantidade inválida');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -421,9 +349,6 @@ export const ApontamentoForm = () => {
|
|||||||
setSaving(true);
|
setSaving(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Validação básica - pode ser expandida depois
|
|
||||||
console.log('✅ Validação de sequência aprovada');
|
|
||||||
|
|
||||||
const apontamentoData: any = {
|
const apontamentoData: any = {
|
||||||
of_number: formData.of_number,
|
of_number: formData.of_number,
|
||||||
tipo_apontamento: itemSelecionado.tipo,
|
tipo_apontamento: itemSelecionado.tipo,
|
||||||
@@ -443,11 +368,8 @@ export const ApontamentoForm = () => {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast.success('Apontamento registrado com sucesso!');
|
toast.success('Apontamento registrado com sucesso!');
|
||||||
|
await refetch();
|
||||||
await Promise.all([
|
resetFormForNewEntry();
|
||||||
refetch(),
|
|
||||||
resetFormForNewEntry()
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro no submit:', error);
|
console.error('Erro no submit:', error);
|
||||||
@@ -475,13 +397,11 @@ export const ApontamentoForm = () => {
|
|||||||
todas_disponiveis: false
|
todas_disponiveis: false
|
||||||
});
|
});
|
||||||
setItemSelecionado(null);
|
setItemSelecionado(null);
|
||||||
setItensDisponiveis({ pecasDisponiveis: [], componentesDisponiveis: [] });
|
|
||||||
setCacheValido(false);
|
setCacheValido(false);
|
||||||
itensCache.clear();
|
|
||||||
toast.success('Cache limpo com sucesso!');
|
toast.success('Cache limpo com sucesso!');
|
||||||
};
|
};
|
||||||
|
|
||||||
const processoSelecionado = null;
|
const isLoadingItens = loadingPecas || loadingApontamentos || loadingComponentes;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
@@ -583,15 +503,12 @@ export const ApontamentoForm = () => {
|
|||||||
<Alert>
|
<Alert>
|
||||||
<Info className="h-4 w-4" />
|
<Info className="h-4 w-4" />
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
{processoSelecionado.ordem === 1
|
{`Processo: ${processoSelecionado.ordem}. ${processoSelecionado.nome}. Selecione as peças ou componentes com saldo pendente para apontar.`}
|
||||||
? `Processo inicial: ${processoSelecionado.nome}. Todos os itens estão disponíveis.`
|
|
||||||
: `Processo ${processoSelecionado.ordem}: ${processoSelecionado.nome}. Apenas itens que passaram pelos processos anteriores estão disponíveis.`
|
|
||||||
}
|
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Seletor de itens otimizado com funcionalidade de lote - agora com scroll */}
|
{/* Seletor de itens otimizado com funcionalidade de lote */}
|
||||||
{formData.processo_id && (
|
{formData.processo_id && (
|
||||||
<div className="max-h-96 overflow-y-auto">
|
<div className="max-h-96 overflow-y-auto">
|
||||||
<SeletorItensOtimizado
|
<SeletorItensOtimizado
|
||||||
@@ -600,7 +517,7 @@ export const ApontamentoForm = () => {
|
|||||||
itemSelecionado={itemSelecionado}
|
itemSelecionado={itemSelecionado}
|
||||||
onItemSelect={handleItemSelect}
|
onItemSelect={handleItemSelect}
|
||||||
onBatchSelect={handleBatchSelect}
|
onBatchSelect={handleBatchSelect}
|
||||||
loading={loadingItens || isProcessingItems}
|
loading={isLoadingItens}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -660,7 +577,7 @@ export const ApontamentoForm = () => {
|
|||||||
</h4>
|
</h4>
|
||||||
{!itemSelecionado ? (
|
{!itemSelecionado ? (
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
Selecione um item para ver as informações ou use os checkboxes para registro em lote
|
Selecione um item para ver as informações ou use os botões para registro em lote
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2 text-sm">
|
||||||
@@ -668,7 +585,7 @@ export const ApontamentoForm = () => {
|
|||||||
<div><strong>Marca:</strong> {itemSelecionado.marca}</div>
|
<div><strong>Marca:</strong> {itemSelecionado.marca}</div>
|
||||||
<div><strong>OF:</strong> {formData.of_number}</div>
|
<div><strong>OF:</strong> {formData.of_number}</div>
|
||||||
<div><strong>Fase:</strong> {formData.fase}</div>
|
<div><strong>Fase:</strong> {formData.fase}</div>
|
||||||
<div><strong>Processo:</strong> {processoSelecionado?.nome || 'N/A'}</div>
|
<div><strong>Processo:</strong> {processoSelecionado ? `${processoSelecionado.ordem}. ${processoSelecionado.nome}` : 'N/A'}</div>
|
||||||
<div><strong>Descrição:</strong> {itemSelecionado.descricao || 'N/A'}</div>
|
<div><strong>Descrição:</strong> {itemSelecionado.descricao || 'N/A'}</div>
|
||||||
<div><strong>Quantidade Disponível:</strong> {itemSelecionado.quantidade_disponivel} unidades</div>
|
<div><strong>Quantidade Disponível:</strong> {itemSelecionado.quantidade_disponivel} unidades</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -676,7 +593,7 @@ export const ApontamentoForm = () => {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Botões movidos para baixo do card de informações */}
|
{/* Botões de ação */}
|
||||||
<div className="flex justify-end space-x-2">
|
<div className="flex justify-end space-x-2">
|
||||||
{formData.of_number && formData.fase && formData.processo_id && (
|
{formData.of_number && formData.fase && formData.processo_id && (
|
||||||
<Button
|
<Button
|
||||||
@@ -690,7 +607,7 @@ export const ApontamentoForm = () => {
|
|||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={saving || !itemSelecionado || !formData.processo_id || loadingItens || isProcessingItems}
|
disabled={saving || !itemSelecionado || !formData.processo_id || isLoadingItens}
|
||||||
className="min-w-32"
|
className="min-w-32"
|
||||||
>
|
>
|
||||||
{saving ? 'Salvando...' : 'Registrar Apontamento'}
|
{saving ? 'Salvando...' : 'Registrar Apontamento'}
|
||||||
|
|||||||
Reference in New Issue
Block a user