diff --git a/src/components/AgendarConsulta/FormNovaConsulta.jsx b/src/components/AgendarConsulta/FormNovaConsulta.jsx index 68f72ea..a17c221 100644 --- a/src/components/AgendarConsulta/FormNovaConsulta.jsx +++ b/src/components/AgendarConsulta/FormNovaConsulta.jsx @@ -2,33 +2,93 @@ import InputMask from "react-input-mask"; import "./style/formagendamentos.css"; import { useState, useEffect } from "react"; - const FormNovaConsulta = ({ onCancel, patientID }) => { - + const [horariosDisponiveis, setHorariosDisponiveis] = useState([]); + const [carregandoHorarios, setCarregandoHorarios] = useState(false); + const [isModoEmergencia, setIsModoEmergencia] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const [anexos, setAnexos] = useState([]); const [loadingAnexos, setLoadingAnexos] = useState(false); - const [paciente, setPaciente] = useState({}) - const [acessibilidade, setAcessibilidade] = useState({cadeirante:false,idoso:false,gravida:false,bebe:false, autista:false }) + const [paciente, setPaciente] = useState({}); + const [acessibilidade, setAcessibilidade] = useState({ + cadeirante: false, + idoso: false, + gravida: false, + bebe: false, + autista: false, + }); const [dadosAtendimento, setDadosAtendimento] = useState({ - profissional: '', - tipoAtendimento: '', - unidade: '', - dataAtendimento: '', - inicio: '', - termino: '', - solicitante: '', - observacoes: '' + profissional: "", + tipoAtendimento: "", + unidade: "", + dataAtendimento: "", + inicio: "", + termino: "", + solicitante: "", + observacoes: "", }); - useEffect(() => { + // Variável de controle para saber se a grade de horário deve ser mostrada + const isReadyForSchedule = + dadosAtendimento.profissional && dadosAtendimento.dataAtendimento; + + const fetchHorariosDisponiveis = async (professionalId, date) => { + if (!isReadyForSchedule || isModoEmergencia) { + setHorariosDisponiveis([]); + return; + } + + setCarregandoHorarios(true); + setHorariosDisponiveis([]); + + var myHeaders = new Headers(); + myHeaders.append("Content-Type", "application/json"); + + const payload = { + doctor_id: professionalId, + date: date, + }; + + var requestOptions = { + method: "POST", + headers: myHeaders, + body: JSON.stringify(payload), + redirect: "follow", + }; + + try { + const res = await fetch( + "https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctor_availability", + requestOptions + ); + const data = await res.json(); + + const slots = data.data && Array.isArray(data.data) ? data.data : []; + + setHorariosDisponiveis(slots); + + // Limpa o horário se o que estava selecionado não existe mais na nova grade + if (dadosAtendimento.inicio && !slots.includes(dadosAtendimento.inicio)) { + setDadosAtendimento((prev) => ({ ...prev, inicio: "", termino: "" })); + } + } catch (err) { + console.error("Erro ao buscar horários disponíveis:", err); + setHorariosDisponiveis([]); + } finally { + setCarregandoHorarios(false); + } + }; + + useEffect(() => { if (!patientID) return; const fetchAnexos = async () => { setLoadingAnexos(true); try { - const res = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos`); + const res = await fetch( + `https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos` + ); const data = await res.json(); setAnexos(data.data || []); } catch (err) { @@ -41,6 +101,23 @@ const FormNovaConsulta = ({ onCancel, patientID }) => { fetchAnexos(); }, [patientID]); + useEffect(() => { + // Chama a busca apenas se estivermos no modo padrão E tivermos profissional e data + if (isReadyForSchedule && !isModoEmergencia) { + fetchHorariosDisponiveis( + dadosAtendimento.profissional, + dadosAtendimento.dataAtendimento + ); + } else if (!isReadyForSchedule) { + setHorariosDisponiveis([]); + } + }, [ + dadosAtendimento.profissional, + dadosAtendimento.dataAtendimento, + isModoEmergencia, + isReadyForSchedule, + ]); + const handleUpload = async () => { if (!selectedFile) return; @@ -48,13 +125,16 @@ const FormNovaConsulta = ({ onCancel, patientID }) => { formData.append("file", selectedFile); try { - const res = await fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos`, { - method: "POST", - body: formData - }); + const res = await fetch( + `https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos`, + { + method: "POST", + body: formData, + } + ); if (res.ok) { const novoAnexo = await res.json(); - setAnexos(prev => [...prev, novoAnexo]); + setAnexos((prev) => [...prev, novoAnexo]); setSelectedFile(null); } else { console.error("Erro ao enviar anexo"); @@ -62,176 +142,216 @@ const FormNovaConsulta = ({ onCancel, patientID }) => { } catch (err) { console.error("Erro ao enviar anexo:", err); } - }; - - - const handleclickAcessibilidade = (id) => { - let resultado = acessibilidade[id] - - if(resultado === false){ setAcessibilidade({...acessibilidade, [id]:true}); console.log('mudou')} - - else if(resultado === true){ setAcessibilidade({...acessibilidade, [id]:false})} - console.log(id) - } - - - const FormatCPF = (valor) => { - console.log(valor) - - const digits = String(valor).replace(/\D/g, '').slice(0, 11); - BuscarPacienteExistentePeloCPF(valor) - - return digits - .replace(/(\d{3})(\d)/, '$1.$2') - .replace(/(\d{3})(\d)/, '$1.$2') - .replace(/(\d{3})(\d{1,2})$/, '$1-$2'); - } - - - const FormatTelefones = (valor) => { - const digits = String(valor).replace(/\D/g, '').slice(0, 11); - return digits - .replace(/(\d)/, '($1') - .replace(/(\d{2})(\d)/, '$1) $2' ) - .replace(/(\d)(\d{4})/, '$1 $2') - .replace(/(\d{4})(\d{4})/, '$1-$2') - } - - - const BuscarCPFnoBancodeDados = async (cpf) => { - - var myHeaders = new Headers(); - myHeaders.append("Authorization", "Bearer "); - myHeaders.append("Content-Type", "application/json"); - - var raw = JSON.stringify({ - "cpf": cpf - }); - - var requestOptions = { - method: 'POST', - headers: myHeaders, - body: raw, - redirect: 'follow' }; - const response = await fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes/validar-cpf", requestOptions); - const result = await response.json(); - return result + const handleclickAcessibilidade = (id) => { + let resultado = acessibilidade[id]; - - } + if (resultado === false) { + setAcessibilidade({ ...acessibilidade, [id]: true }); + console.log("mudou"); + } else if (resultado === true) { + setAcessibilidade({ ...acessibilidade, [id]: false }); + } + console.log(id); + }; - const BuscarPacienteExistentePeloCPF = async (value) => { - - if(isNaN(value[13]) === false && value.length === 14)try { - const result = await BuscarCPFnoBancodeDados(value); - console.log("Resultado:", result); - - if (result.data.existe === true){ + const FormatCPF = (valor) => { + const digits = String(valor).replace(/\D/g, "").slice(0, 11); + BuscarPacienteExistentePeloCPF(valor); - var myHeaders = new Headers(); + return digits + .replace(/(\d{3})(\d)/, "$1.$2") + .replace(/(\d{3})(\d)/, "$1.$2") + .replace(/(\d{3})(\d{1,2})$/, "$1-$2"); + }; + + const FormatTelefones = (valor) => { + const digits = String(valor).replace(/\D/g, "").slice(0, 11); + return digits + .replace(/(\d)/, "($1") + .replace(/(\d{2})(\d)/, "$1) $2") + .replace(/(\d)(\d{4})/, "$1 $2") + .replace(/(\d{4})(\d{4})/, "$1-$2"); + }; + + const BuscarCPFnoBancodeDados = async (cpf) => { + var myHeaders = new Headers(); myHeaders.append("Authorization", "Bearer "); + myHeaders.append("Content-Type", "application/json"); + + var raw = JSON.stringify({ + cpf: cpf, + }); var requestOptions = { - method: 'GET', + method: "POST", headers: myHeaders, - redirect: 'follow' + body: raw, + redirect: "follow", }; - fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes/", requestOptions) - .then(response => response.json()) - .then(result => setPaciente(result.data)) - .catch(error => console.log('error', error)); - } - + const response = await fetch( + "https://mock.apidog.com/m1/1053378-0-default/pacientes/validar-cpf", + requestOptions + ); + const result = await response.json(); + return result; + }; + const BuscarPacienteExistentePeloCPF = async (value) => { + if (isNaN(value[13]) === false && value.length === 14) + try { + const result = await BuscarCPFnoBancodeDados(value); - } catch (error) { - console.log("error", error); - } - //BuscarCPFnoBancodeDados(value) - } + if (result.data.existe === true) { + var myHeaders = new Headers(); + myHeaders.append("Authorization", "Bearer "); + + var requestOptions = { + method: "GET", + headers: myHeaders, + redirect: "follow", + }; + + fetch( + "https://mock.apidog.com/m1/1053378-0-default/pacientes/", + requestOptions + ) + .then((response) => response.json()) + .then((result) => setPaciente(result.data)) + .catch((error) => console.log("error", error)); + } + } catch (error) { + console.log("error", error); + } + }; const handleChange = (e) => { + const { value, name } = e.target; - const {value, name} = e.target; - - console.log(value, name) - - if(name === 'email'){ - setPaciente({...paciente, contato:{ - ...paciente.contato, - email:value - }}) - - } else if(name === 'telefone'){ - setPaciente({...paciente, contato:{ - ...paciente.contato, - telefone1:FormatTelefones(value) - }}) + if (name === "email") { + setPaciente({ + ...paciente, + contato: { + ...paciente.contato, + email: value, + }, + }); + } else if (name === "telefone") { + setPaciente({ + ...paciente, + contato: { + ...paciente.contato, + telefone1: FormatTelefones(value), + }, + }); + } else { + setPaciente({ ...paciente, [name]: value }); } - else{ - setPaciente({...paciente,[name]:value}) - } - } + }; const handleAtendimentoChange = (e) => { const { value, name } = e.target; - setDadosAtendimento(prev => ({ + setDadosAtendimento((prev) => ({ ...prev, - [name]: value + [name]: value, })); }; - const handleSubmitExcecao = async () => { - console.log("Modo Emergência Ativado: Tentando criar Exceção com novo endpoint."); + const handleSubmitExcecao = async () => { + console.log( + "Modo Emergência Ativado: Tentando criar Exceção com novo endpoint." + ); - const { profissional, dataAtendimento, tipoAtendimento, inicio, termino, observacoes } = dadosAtendimento; + const { + profissional, + dataAtendimento, + tipoAtendimento, + inicio, + termino, + observacoes, + } = dadosAtendimento; - if (!profissional || !dataAtendimento || !tipoAtendimento || !inicio || !termino) { - alert("Por favor, preencha o Profissional, Data, Tipo e Horários para a exceção."); - return; + if ( + !profissional || + !dataAtendimento || + !tipoAtendimento || + !inicio || + !termino + ) { + alert( + "Por favor, preencha o Profissional, Data, Tipo e Horários para a exceção." + ); + return; } const payload = { doctor_id: profissional, date: dataAtendimento, - start_time: inicio + ":00", // Adiciona ":00" se o input type="time" retornar apenas HH:MM - end_time: termino + ":00", // Adiciona ":00" - kind: "liberacao", // Usando 'excecao' ou 'consulta' ao invés de 'bloqueio' + start_time: inicio + ":00", + end_time: termino + ":00", + kind: "liberacao", reason: tipoAtendimento, - //observation: observacoes || "Agendamento fora da grade horária padrão.", }; - + var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); var requestOptions = { - method: 'POST', + method: "POST", headers: myHeaders, body: JSON.stringify(payload), - redirect: 'follow' - }; + redirect: "follow", + }; try { - const response = await fetch("https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctor_exceptions", requestOptions); + const response = await fetch( + "https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctor_exceptions", + requestOptions + ); const result = await response.json(); if (response.ok || response.status === 201) { console.log("Exceção de emergência criada com sucesso:", result); - alert(`Consulta de emergência agendada como exceção! Detalhes: ${JSON.stringify(result)}`); + alert( + `Consulta de emergência agendada como exceção! Detalhes: ${JSON.stringify( + result + )}` + ); } else { console.error("Erro ao criar exceção de emergência:", result); - alert(`Erro ao agendar exceção. Status: ${response.status}. Detalhes: ${result.message || JSON.stringify(result)}`); + alert( + `Erro ao agendar exceção. Status: ${response.status}. Detalhes: ${ + result.message || JSON.stringify(result) + }` + ); } } catch (error) { console.error("Erro na requisição para criar exceção:", error); - alert("Erro de comunicação com o servidor ou formato de resposta inválido."); + alert( + "Erro de comunicação com o servidor ou formato de resposta inválido." + ); } }; const handleSubmitPadrao = () => { + if (!isReadyForSchedule) { + alert( + "Por favor, preencha o Profissional e a Data do Atendimento antes de salvar." + ); + return; + } + if ( + !horariosDisponiveis.includes(dadosAtendimento.inicio) || + !horariosDisponiveis.includes(dadosAtendimento.termino) + ) { + alert( + "Por favor, selecione horários válidos dentro da grade do profissional." + ); + return; + } + console.log("Salvando agendamento."); alert("Agendamento salvo!"); }; @@ -239,89 +359,135 @@ const FormNovaConsulta = ({ onCancel, patientID }) => { const handleSubmit = (e) => { e.preventDefault(); if (isModoEmergencia) { - handleSubmitExcecao(); + handleSubmitExcecao(); } else { - handleSubmitPadrao(); + handleSubmitPadrao(); } }; return (
- -

Informações do paciente

-
+
- +
- - e.target.value = FormatCPF(e.target.value)} /> - + + (e.target.value = FormatCPF(e.target.value))} + />
- +
-
+
-
+
- +
- +
- +
-
+
-
- -
- - +
+
+ + +
+
+ + +
+ +
+ + +
-
- - -
- -
- - -
-

Informações adicionais

- - - setSelectedFile(e.target.files[0])} - /> - {selectedFile && ( - - )} + + + setSelectedFile(e.target.files[0])} + /> + {selectedFile && ( + + )}
{loadingAnexos ? (

Carregando anexos...

@@ -335,90 +501,160 @@ const FormNovaConsulta = ({ onCancel, patientID }) => {

Informações do atendimento

- - {isModoEmergencia && ( -

⚠️ As informações de data e horário serão enviadas como uma exceção fora da grade normal.

- )} + + {isModoEmergencia && ( +

+ ⚠️ As informações de data e horário serão enviadas como uma + exceção fora da grade normal. +

+ )}
-
-
handleclickAcessibilidade(e.currentTarget.id)}> - - accessible -
- -
handleclickAcessibilidade(e.currentTarget.id)}> - elderly -
- -
handleclickAcessibilidade(e.currentTarget.id)}> - pregnant_woman -
- -
handleclickAcessibilidade(e.currentTarget.id)}> - - -
- -
handleclickAcessibilidade(e.currentTarget.id)}> - -
- +
+
handleclickAcessibilidade(e.currentTarget.id)} + > + accessible
-
-
- - -
-
- - -
+
handleclickAcessibilidade(e.currentTarget.id)} + > + elderly
+
handleclickAcessibilidade(e.currentTarget.id)} + > + + pregnant_woman + +
+ +
handleclickAcessibilidade(e.currentTarget.id)} + > + + + + + + +
+ +
handleclickAcessibilidade(e.currentTarget.id)} + > + + + +
+
+ +
+
+ + {/* INPUT: Nome do profissional (usado para habilitar a busca de horários) */} + +
+
+ + +
+
+
-
-
+
-
- +
- @@ -426,36 +662,118 @@ const FormNovaConsulta = ({ onCancel, patientID }) => {
-
- - -
+ {isModoEmergencia ? ( + // MODO EMERGÊNCIA: Input type="time" simples, sem restrição + <> +
+ + +
+
+ + +
+ + ) : // MODO PADRÃO + isReadyForSchedule ? ( + // ESTADO 2: Médico e Data ESCOLHIDOS -> Restringe para grade (SELECT) + <> +
+ + {carregandoHorarios ? ( + + ) : ( + + )} +
+ +
+ + +
+ + ) : ( + // ESTADO 1: Médico ou Data PENDENTE -> Permite entrada de tempo livre (INPUT TYPE="TIME") + <> +
+ + +
+
+ + +
+ + )} -
- - -
-
- @@ -463,13 +781,12 @@ const FormNovaConsulta = ({ onCancel, patientID }) => {
-
- +
-