diff --git a/scripts/fix-uuid.sql b/scripts/fix-uuid.sql new file mode 100644 index 0000000..0ec4191 --- /dev/null +++ b/scripts/fix-uuid.sql @@ -0,0 +1,9 @@ +-- Identificar registros com UUID inválido +SELECT id, uuid_column +FROM atendimento +WHERE uuid_column !~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'; + +-- Atualizar registros com UUID inválido +UPDATE atendimento +SET uuid_column = gen_random_uuid() +WHERE uuid_column !~ '^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'; diff --git a/src/components/clientes/ClienteModal.tsx b/src/components/clientes/ClienteModal.tsx index c17000a..e4c0c7e 100644 --- a/src/components/clientes/ClienteModal.tsx +++ b/src/components/clientes/ClienteModal.tsx @@ -200,7 +200,7 @@ export const ClienteModal: React.FC = ({ // Monitorar o valor do CEP para autopreenchimento const cepValue = watch("cep"); - // Função para buscar dados do CEP - versão com gerenciamento de estados do componente + // Função para buscar dados do CEP - versão corrigida const fetchAddressByCep = useCallback(async (cep: string) => { if (!cep || cep.length !== 8) return; @@ -213,7 +213,6 @@ export const ClienteModal: React.FC = ({ if (response.data && !response.data.erro) { // Usar estado local para garantir re-renderização imediata - // Forçar preenchimento dos campos e atualização da interface const endereco = response.data.logradouro || ""; const bairro = response.data.bairro || ""; const cidade = response.data.localidade || ""; @@ -225,8 +224,7 @@ export const ClienteModal: React.FC = ({ setValue("cidade", cidade, { shouldValidate: true }); setValue("estado", estado, { shouldValidate: true }); - // Garantir re-renderização do componente - // Esta é a parte crucial: forçar o componente a re-renderizar com novo estado + // Atualizar o estado para re-renderização do componente setEnderecoState({ endereco, bairro, @@ -235,13 +233,23 @@ export const ClienteModal: React.FC = ({ preenchido: true, }); - // Focar no próximo campo - setTimeout(() => { - const numeroInput = document.querySelector( - 'input[name="numero"]' - ) as HTMLInputElement; - if (numeroInput) numeroInput.focus(); - }, 100); + // Focar no próximo campo apenas se o usuário não estiver digitando ativamente + // Esta alteração evita interromper o fluxo natural de preenchimento + const activeElement = document.activeElement; + const isUserTyping = + activeElement && + (activeElement.tagName === 'INPUT' || activeElement.tagName === 'SELECT') && + activeElement !== document.querySelector('input[name="cep"]'); + + // Só focar no campo número se o usuário não estiver digitando em outro campo + if (!isUserTyping) { + setTimeout(() => { + const numeroInput = document.querySelector( + 'input[name="numero"]' + ) as HTMLInputElement; + if (numeroInput) numeroInput.focus(); + }, 100); + } } else { console.error("CEP não encontrado"); alert("CEP não encontrado. Por favor, verifique o CEP informado."); diff --git a/src/server/index.ts b/src/server/index.ts index a017f0a..edd8513 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -55,6 +55,12 @@ const orgaoJulgadorRepository = new OrgaoJulgadorRepository(); const custaProcessualRepository = new CustaProcessualRepository(); const honorarioRepository = new HonorarioRepository(); +// Adicionar função de validação de UUID no início do arquivo +const isValidUUID = (uuid: string): boolean => { + const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + return uuidRegex.test(uuid); +}; + // Middleware para extrair usuário do token // Remover este middleware pois já temos o auth.ts // const extractUser = (req: any, res: any, next: any) => { ... } @@ -1000,7 +1006,7 @@ app.post("/api/atendimentos", authMiddleware, async (req, res) => { conteudo, cliente: { connect: { id: clienteId } }, usuario: { connect: { id: req.user!.id } }, - ...(processoId && { processo: { connect: { id: processoId } } }), + ...(processoId && { processo: { connect: { id: processoId } }), status: 'ATIVO', dataAtualizacao: new Date(), }, @@ -1337,6 +1343,54 @@ app.delete("/api/agendamentos/:id", authMiddleware, async (req, res) => { } }); +// Atualizar a rota de agendamentos +app.get("/api/atendimentos/agendamentos", async (req, res) => { + try { + const { data } = req.query; + + if (!data || typeof data !== 'string') { + return res.status(400).json({ error: 'Data inválida' }); + } + + const dataConsulta = new Date(data); + if (isNaN(dataConsulta.getTime())) { + return res.status(400).json({ error: 'Formato de data inválido' }); + } + + const agendamentos = await prisma.agendamentoAtendimento.findMany({ + where: { + data: { + gte: dataConsulta, + lt: new Date(dataConsulta.setDate(dataConsulta.getDate() + 1)) + } + }, + include: { + cliente: true, + usuario: { + select: { + id: true, + nome: true + } + } + } + }); + + const validAgendamentos = agendamentos.filter(agendamento => + isValidUUID(agendamento.id) && + isValidUUID(agendamento.clienteId) && + isValidUUID(agendamento.usuarioId) + ); + + res.json(validAgendamentos); + } catch (error) { + console.error('Erro ao buscar agendamentos:', error); + res.status(500).json({ + error: 'Erro ao buscar agendamentos', + details: error instanceof Error ? error.message : 'Erro desconhecido' + }); + } +}); + // Erro handling middleware app.use( (