From f2fd8bd699ccf107c89fe12e4189c1f3aafd6825 Mon Sep 17 00:00:00 2001 From: Marcos Reifonas Date: Fri, 21 Aug 2026 14:32:52 +0000 Subject: [PATCH] fix(cronograma): corrigir salvamento e atualizacao automatica da lista de cronogramas --- src/components/cronograma/CronogramaForm.tsx | 6 +- src/hooks/useCronogramaOperations.tsx | 250 +------------------ src/hooks/useCronogramas.tsx | 122 +++++---- src/pages/CronogramaOF.tsx | 6 + 4 files changed, 88 insertions(+), 296 deletions(-) diff --git a/src/components/cronograma/CronogramaForm.tsx b/src/components/cronograma/CronogramaForm.tsx index 62b16d7..f17b5d7 100644 --- a/src/components/cronograma/CronogramaForm.tsx +++ b/src/components/cronograma/CronogramaForm.tsx @@ -20,6 +20,7 @@ interface CronogramaFormProps { cronograma?: CronogramaOf | null; onClose: () => void; isOpen: boolean; + onSaveSuccess?: () => void; } const processosDefault = [ @@ -30,7 +31,7 @@ const processosDefault = [ 'Aceite/DB' ]; -export const CronogramaForm: React.FC = ({ cronograma, onClose, isOpen }) => { +export const CronogramaForm: React.FC = ({ cronograma, onClose, isOpen, onSaveSuccess }) => { const { saveCronograma, getCronogramaPorOf } = useCronogramaOperations(); const [formData, setFormData] = useState({ of_id: '', @@ -228,6 +229,9 @@ export const CronogramaForm: React.FC = ({ cronograma, onCl setLoading(false); if (success) { + if (onSaveSuccess) { + onSaveSuccess(); + } onClose(); } }; diff --git a/src/hooks/useCronogramaOperations.tsx b/src/hooks/useCronogramaOperations.tsx index 32b64bf..7f00835 100644 --- a/src/hooks/useCronogramaOperations.tsx +++ b/src/hooks/useCronogramaOperations.tsx @@ -1,249 +1 @@ - -import { useState, useEffect } from 'react'; -import { supabase } from '@/integrations/supabase/client'; -import { toast } from 'sonner'; -import { useAuth } from './useAuth'; -import { CronogramaOf } from '@/types/cronograma'; - -export const useCronogramaOperations = () => { - const { user } = useAuth(); - const [cronogramas, setCronogramas] = useState([]); - const [loading, setLoading] = useState(false); - - const loadCronogramas = async () => { - try { - setLoading(true); - - const { data: cronogramasData, error: cronogramasError } = await supabase - .from('cronogramas_of') - .select(` - *, - ordens_fabricacao ( - num_of, - descritivo - ), - profiles!cronogramas_of_gestor_id_fkey ( - full_name, - email - ) - `) - .order('created_at', { ascending: false }); - - if (cronogramasError) throw cronogramasError; - - // Carregar processos para cada cronograma - const cronogramasComProcessos = await Promise.all( - (cronogramasData || []).map(async (cronograma) => { - const { data: processos, error: processosError } = await supabase - .from('processos_cronograma') - .select('*') - .eq('cronograma_id', cronograma.id) - .order('ordem'); - - if (processosError) throw processosError; - - return { - id: cronograma.id, - of_id: cronograma.of_id, - gestor_id: cronograma.gestor_id, - revisao: cronograma.revisao, - processos: processos || [], - ordem_fabricacao: cronograma.ordens_fabricacao, - gestor_profile: cronograma.profiles - } as CronogramaOf; - }) - ); - - setCronogramas(cronogramasComProcessos); - } catch (error) { - console.error('Erro ao carregar cronogramas:', error); - toast.error('Erro ao carregar cronogramas'); - } finally { - setLoading(false); - } - }; - - const saveCronograma = async (cronograma: Partial & { processos: any[] }) => { - try { - if (!user) throw new Error('Usuário não autenticado'); - - let cronogramaId: string; - - if (cronograma.id) { - // Atualizar cronograma existente - const novaRevisao = cronograma.revisao ? cronograma.revisao + 1 : 1; - - const { data: updatedCronograma, error: updateError } = await supabase - .from('cronogramas_of') - .update({ - gestor_id: cronograma.gestor_id, - revisao: novaRevisao, - updated_at: new Date().toISOString() - }) - .eq('id', cronograma.id) - .select() - .single(); - - if (updateError) throw updateError; - cronogramaId = updatedCronograma.id; - - // Deletar processos antigos - const { error: deleteError } = await supabase - .from('processos_cronograma') - .delete() - .eq('cronograma_id', cronogramaId); - - if (deleteError) throw deleteError; - } else { - // Verificar se já existe cronograma para esta OF - const { data: existingCronograma } = await supabase - .from('cronogramas_of') - .select('id, revisao') - .eq('of_id', cronograma.of_id) - .single(); - - if (existingCronograma) { - // Atualizar cronograma existente - const novaRevisao = existingCronograma.revisao + 1; - - const { data: updatedCronograma, error: updateError } = await supabase - .from('cronogramas_of') - .update({ - gestor_id: cronograma.gestor_id, - revisao: novaRevisao, - updated_at: new Date().toISOString() - }) - .eq('id', existingCronograma.id) - .select() - .single(); - - if (updateError) throw updateError; - cronogramaId = updatedCronograma.id; - - // Deletar processos antigos - const { error: deleteError } = await supabase - .from('processos_cronograma') - .delete() - .eq('cronograma_id', cronogramaId); - - if (deleteError) throw deleteError; - } else { - // Criar novo cronograma - const { data: newCronograma, error: insertError } = await supabase - .from('cronogramas_of') - .insert({ - of_id: cronograma.of_id, - gestor_id: cronograma.gestor_id, - revisao: 1, - created_by: user.id - }) - .select() - .single(); - - if (insertError) throw insertError; - cronogramaId = newCronograma.id; - } - } - - // Inserir novos processos - const processosParaInserir = cronograma.processos.map(processo => ({ - cronograma_id: cronogramaId, - nome_processo: processo.nome_processo, - data_inicio: processo.data_inicio, - data_fim: processo.data_fim, - ordem: processo.ordem - })); - - const { error: processosError } = await supabase - .from('processos_cronograma') - .insert(processosParaInserir); - - if (processosError) throw processosError; - - toast.success('Cronograma salvo com sucesso!'); - loadCronogramas(); - return true; - } catch (error) { - console.error('Erro ao salvar cronograma:', error); - toast.error('Erro ao salvar cronograma'); - return false; - } - }; - - const deleteCronograma = async (cronogramaId: string) => { - try { - const { error } = await supabase - .from('cronogramas_of') - .delete() - .eq('id', cronogramaId); - - if (error) throw error; - - toast.success('Cronograma removido com sucesso!'); - loadCronogramas(); - return true; - } catch (error) { - console.error('Erro ao deletar cronograma:', error); - toast.error('Erro ao remover cronograma'); - return false; - } - }; - - const getCronogramaPorOf = async (ofId: string) => { - try { - const { data: cronograma, error } = await supabase - .from('cronogramas_of') - .select(` - *, - ordens_fabricacao ( - num_of, - descritivo - ), - profiles!cronogramas_of_gestor_id_fkey ( - full_name, - email - ) - `) - .eq('of_id', ofId) - .single(); - - if (error && error.code !== 'PGRST116') throw error; - - if (!cronograma) return null; - - const { data: processos, error: processosError } = await supabase - .from('processos_cronograma') - .select('*') - .eq('cronograma_id', cronograma.id) - .order('ordem'); - - if (processosError) throw processosError; - - return { - id: cronograma.id, - of_id: cronograma.of_id, - gestor_id: cronograma.gestor_id, - revisao: cronograma.revisao, - processos: processos || [], - ordem_fabricacao: cronograma.ordens_fabricacao, - gestor_profile: cronograma.profiles - } as CronogramaOf; - } catch (error) { - console.error('Erro ao buscar cronograma:', error); - return null; - } - }; - - useEffect(() => { - loadCronogramas(); - }, []); - - return { - cronogramas, - loading, - loadCronogramas, - saveCronograma, - deleteCronograma, - getCronogramaPorOf - }; -}; +export { useCronogramas as useCronogramaOperations } from './useCronogramas'; diff --git a/src/hooks/useCronogramas.tsx b/src/hooks/useCronogramas.tsx index 607e7fa..268af7d 100644 --- a/src/hooks/useCronogramas.tsx +++ b/src/hooks/useCronogramas.tsx @@ -37,7 +37,7 @@ export const useCronogramas = () => { const loadCronogramas = async () => { try { setLoading(true); - + const { data: cronogramasData, error: cronogramasError } = await supabase .from('cronogramas_of') .select(` @@ -47,7 +47,7 @@ export const useCronogramas = () => { descritivo, peso_total ), - profiles!gestor_id ( + profiles!cronogramas_of_gestor_id_fkey ( full_name, email ) @@ -89,24 +89,18 @@ export const useCronogramas = () => { } }; - const saveCronograma = async (cronograma: Omit) => { + const saveCronograma = async (cronograma: Partial & { processos: ProcessoCronograma[] }) => { try { if (!user) throw new Error('Usuário não autenticado'); - - // Verificar se já existe cronograma para esta OF - const { data: existingCronograma } = await supabase - .from('cronogramas_of') - .select('id, revisao') - .eq('of_id', cronograma.of_id) - .single(); + if (!cronograma.of_id) throw new Error('Selecione uma Ordem de Fabricação'); + if (!cronograma.gestor_id) throw new Error('Selecione o gestor responsável'); let cronogramaId: string; - let novaRevisao = 1; - if (existingCronograma) { - // Atualizar cronograma existente - novaRevisao = existingCronograma.revisao + 1; - + if (cronograma.id) { + // Atualizar cronograma existente por ID + const novaRevisao = cronograma.revisao ? cronograma.revisao + 1 : 1; + const { data: updatedCronograma, error: updateError } = await supabase .from('cronogramas_of') .update({ @@ -114,7 +108,7 @@ export const useCronogramas = () => { revisao: novaRevisao, updated_at: new Date().toISOString() }) - .eq('id', existingCronograma.id) + .eq('id', cronograma.id) .select() .single(); @@ -129,43 +123,80 @@ export const useCronogramas = () => { if (deleteError) throw deleteError; } else { - // Criar novo cronograma - const { data: newCronograma, error: insertError } = await supabase + // Verificar se já existe cronograma para esta OF (usando maybeSingle para evitar erro PGRST116) + const { data: existingCronograma } = await supabase .from('cronogramas_of') - .insert({ - of_id: cronograma.of_id, - gestor_id: cronograma.gestor_id, - revisao: 1, - created_by: user.id - }) - .select() - .single(); + .select('id, revisao') + .eq('of_id', cronograma.of_id) + .maybeSingle(); - if (insertError) throw insertError; - cronogramaId = newCronograma.id; + if (existingCronograma) { + // Atualizar cronograma existente + const novaRevisao = (existingCronograma.revisao || 1) + 1; + + const { data: updatedCronograma, error: updateError } = await supabase + .from('cronogramas_of') + .update({ + gestor_id: cronograma.gestor_id, + revisao: novaRevisao, + updated_at: new Date().toISOString() + }) + .eq('id', existingCronograma.id) + .select() + .single(); + + if (updateError) throw updateError; + cronogramaId = updatedCronograma.id; + + // Deletar processos antigos + const { error: deleteError } = await supabase + .from('processos_cronograma') + .delete() + .eq('cronograma_id', cronogramaId); + + if (deleteError) throw deleteError; + } else { + // Criar novo cronograma + const { data: newCronograma, error: insertError } = await supabase + .from('cronogramas_of') + .insert({ + of_id: cronograma.of_id, + gestor_id: cronograma.gestor_id, + revisao: 1, + created_by: user.id + }) + .select() + .single(); + + if (insertError) throw insertError; + cronogramaId = newCronograma.id; + } } // Inserir novos processos - const processosParaInserir = cronograma.processos.map(processo => ({ - cronograma_id: cronogramaId, - nome_processo: processo.nome_processo, - data_inicio: processo.data_inicio, - data_fim: processo.data_fim, - ordem: processo.ordem - })); + if (cronograma.processos && cronograma.processos.length > 0) { + const processosParaInserir = cronograma.processos.map((processo, idx) => ({ + cronograma_id: cronogramaId, + nome_processo: processo.nome_processo, + data_inicio: processo.data_inicio, + data_fim: processo.data_fim, + ordem: processo.ordem || idx + 1 + })); - const { error: processosError } = await supabase - .from('processos_cronograma') - .insert(processosParaInserir); + const { error: processosError } = await supabase + .from('processos_cronograma') + .insert(processosParaInserir); - if (processosError) throw processosError; + if (processosError) throw processosError; + } toast.success('Cronograma salvo com sucesso!'); - loadCronogramas(); + await loadCronogramas(); return true; } catch (error) { console.error('Erro ao salvar cronograma:', error); - toast.error('Erro ao salvar cronograma'); + const errMsg = error instanceof Error ? error.message : 'Erro ao salvar cronograma'; + toast.error(errMsg); return false; } }; @@ -180,7 +211,7 @@ export const useCronogramas = () => { if (error) throw error; toast.success('Cronograma removido com sucesso!'); - loadCronogramas(); + await loadCronogramas(); return true; } catch (error) { console.error('Erro ao deletar cronograma:', error); @@ -200,16 +231,15 @@ export const useCronogramas = () => { descritivo, peso_total ), - profiles!gestor_id ( + profiles!cronogramas_of_gestor_id_fkey ( full_name, email ) `) .eq('of_id', ofId) - .single(); - - if (error && error.code !== 'PGRST116') throw error; + .maybeSingle(); + if (error) throw error; if (!cronograma) return null; const { data: processos, error: processosError } = await supabase diff --git a/src/pages/CronogramaOF.tsx b/src/pages/CronogramaOF.tsx index 251c760..4ef1576 100644 --- a/src/pages/CronogramaOF.tsx +++ b/src/pages/CronogramaOF.tsx @@ -68,6 +68,11 @@ const CronogramaOF = () => { setSelectedCronograma(null); }; + const handleSaveSuccess = () => { + loadCronogramas(); + setActiveTab('cronogramas'); + }; + const handleCloseGanttChart = () => { setShowGanttChart(false); setCronogramaForGantt(null); @@ -285,6 +290,7 @@ const CronogramaOF = () => { cronograma={selectedCronograma} onClose={handleCloseCronogramaForm} isOpen={showCronogramaForm} + onSaveSuccess={handleSaveSuccess} /> )}