2025-10-15 16:50:35 -03:00

491 lines
17 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import InputMask from "react-input-mask";
import "./style/formagendamentos.css";
import { useState, useEffect } from "react";
const FormNovaConsulta = ({ onCancel, patientID }) => {
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 [dadosAtendimento, setDadosAtendimento] = useState({
profissional: '',
tipoAtendimento: '',
unidade: '',
dataAtendimento: '',
inicio: '',
termino: '',
solicitante: '',
observacoes: ''
});
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 data = await res.json();
setAnexos(data.data || []);
} catch (err) {
console.error("Erro ao buscar anexos:", err);
} finally {
setLoadingAnexos(false);
}
};
fetchAnexos();
}, [patientID]);
const handleUpload = async () => {
if (!selectedFile) return;
const formData = new FormData();
formData.append("file", selectedFile);
try {
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]);
setSelectedFile(null);
} else {
console.error("Erro ao enviar anexo");
}
} 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 <token>");
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 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){
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer <token>");
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);
}
//BuscarCPFnoBancodeDados(value)
}
const handleChange = (e) => {
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)
}})
}
else{
setPaciente({...paciente,[name]:value})
}
}
const handleAtendimentoChange = (e) => {
const { value, name } = e.target;
setDadosAtendimento(prev => ({
...prev,
[name]: value
}));
};
const handleSubmitExcecao = async () => {
console.log("Modo Emergência Ativado: Tentando criar Exceção com novo endpoint.");
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;
}
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'
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',
headers: myHeaders,
body: JSON.stringify(payload),
redirect: 'follow'
};
try {
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)}`);
} 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)}`);
}
} 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.");
}
};
const handleSubmitPadrao = () => {
console.log("Salvando agendamento.");
alert("Agendamento salvo!");
};
const handleSubmit = (e) => {
e.preventDefault();
if (isModoEmergencia) {
handleSubmitExcecao();
} else {
handleSubmitPadrao();
}
};
return (
<div className="form-container">
<form className="form-agendamento" onSubmit={handleSubmit}>
<h2 className="section-title">Informações do paciente</h2>
<div className="campos-informacoes-paciente" id="informacoes-paciente-linha-um">
<div className="campo-de-input">
<label>Nome *</label>
<input type="text" name="nome" value={paciente.nome} placeholder="Insira o nome do paciente" required onChange={handleChange} />
</div>
<div className="campo-de-input">
<label>CPF do paciente</label>
<input type="text" name="cpf" placeholder="000.000.000-00" onChange={(e) => e.target.value = FormatCPF(e.target.value)} />
</div>
<div className="campo-de-input">
<label>RG</label>
<input type="text" name="rg" placeholder="Insira o nº do RG" maxLength={9} />
</div>
</div>
<div className="campos-informacoes-paciente" id="informacoes-paciente-linha-dois">
<div className="campo-de-input">
<label>Data de nascimento *</label>
<input type="date" name="data_nascimento" value={paciente.data_nascimento} required onChange={handleChange}/>
</div>
<div className="campo-de-input">
<label>Telefone</label>
<input type="tel" name="telefone" placeholder="(99) 99999-9999" value={paciente.contato?.telefone1} onChange={handleChange} />
</div>
<div className="campo-de-input">
<label>E-mail</label>
<input type="email" name="email" placeholder="Email" value={paciente.contato?.email} onChange={handleChange} />
</div>
</div>
<div className="campos-informacoes-paciente" id="informacoes-paciente-linha-tres">
<div className="campo-de-input">
<label>Convênio</label>
<select name="convenio">
<option value="particular">Particular</option>
<option value="publico">Público</option>
</select>
</div>
<div className="campo-de-input">
<label>Matrícula</label>
<input type="text" name="matricula" placeholder="000000000" />
</div>
<div className="campo-de-input">
<label>Validade</label>
<input type="date" name="validade" />
</div>
</div>
<h3 className="section-subtitle">Informações adicionais</h3>
<label htmlFor="anexo-input" className="btn btn-secondary">Adicionar Anexo</label>
<input
type="file"
id="anexo-input"
className="d-none"
onChange={(e) => setSelectedFile(e.target.files[0])}
/>
{selectedFile && (
<button type="button" className="btn btn-primary ms-2" onClick={handleUpload}>
Enviar
</button>
)}
<div className="anexos-list">
{loadingAnexos ? (
<p>Carregando anexos...</p>
) : (
anexos.map((anexo, index) => (
<div key={index} className="anexo-item">
<span>{anexo.nome || anexo.fileName}</span>
</div>
))
)}
</div>
<h2 className="section-title">Informações do atendimento</h2>
<div className="emergencia-toggle-container">
<button
type="button"
className={`btn ${isModoEmergencia ? 'btn-danger' : 'btn-secondary'}`}
onClick={() => setIsModoEmergencia(prev => !prev)}
style={{ marginBottom: '15px' }}
>
{isModoEmergencia ? 'Modo: EMERGÊNCIA Ativo' : 'Ativar Modo: Emergência (Exceção)'}
</button>
{isModoEmergencia && (
<p className="alerta-emergencia"> As informações de data e horário serão enviadas como uma exceção fora da grade normal.</p>
)}
</div>
<div className="icons-container">
<div className={`icons-div ${ acessibilidade.cadeirante === true ? 'acessibilidade-ativado' : ''} `} id='cadeirante' onClick={(e) => handleclickAcessibilidade(e.currentTarget.id)}>
<span className="material-symbols-outlined icon">accessible</span>
</div>
<div className={`icons-div ${acessibilidade.idoso === true ? 'acessibilidade-ativado' : ''}`} id="idoso" onClick={(e) => handleclickAcessibilidade(e.currentTarget.id)}>
<span className="material-symbols-outlined icon">elderly</span>
</div>
<div className={`icons-div ${acessibilidade.gravida === true ? 'acessibilidade-ativado' : ''}`} id="gravida" onClick={(e) => handleclickAcessibilidade(e.currentTarget.id)}>
<span className="material-symbols-outlined icon">pregnant_woman</span>
</div>
<div className={`icons-div ${acessibilidade.bebe === true ? 'acessibilidade-ativado' : ''}`} id="bebe" onClick={(e) => handleclickAcessibilidade(e.currentTarget.id)}>
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-baby-icon lucide-baby"><path d="M10 16c.5.3 1.2.5 2 .5s1.5-.2 2-.5"/><path d="M15 12h.01"/><path d="M19.38 6.813A9 9 0 0 1 20.8 10.2a2 2 0 0 1 0 3.6 9 9 0 0 1-17.6 0 2 2 0 0 1 0-3.6A9 9 0 0 1 12 3c2 0 3.5 1.1 3.5 2.5s-.9 2.5-2 2.5c-.8 0-1.5-.4-1.5-1"/><path d="M9 12h.01"/></svg>
</div>
<div className={`icons-div ${acessibilidade.autista === true ? 'acessibilidade-ativado' : ''}`} id="autista" onClick={(e) => handleclickAcessibilidade(e.currentTarget.id)}>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.75" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-puzzle-icon lucide-puzzle"><path d="M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"/></svg>
</div>
</div>
<div className="campo-informacoes-atendimento">
<div className="campo-de-input">
<label>Nome do profissional *</label>
<input
type="text"
name="profissional"
required
value={dadosAtendimento.profissional}
onChange={handleAtendimentoChange}
/>
</div>
<div className="campo-de-input">
<label>Tipo de atendimento *</label>
<input
type="text"
name="tipoAtendimento"
required
value={dadosAtendimento.tipoAtendimento}
onChange={handleAtendimentoChange}
/>
</div>
</div>
<section id="informacoes-atendimento-segunda-linha">
<section id="informacoes-atendimento-segunda-linha-esquerda">
<div className="campo-informacoes-atendimento">
<div className='campo-de-input'>
<label>Unidade *</label>
<select
name="unidade"
value={dadosAtendimento.unidade}
onChange={handleAtendimentoChange}
>
<option value="" disabled invisible selected>Selecione a unidade</option>
<option value="centro">Núcleo de Especialidades Integradas</option>
<option value="leste">Unidade Leste</option>
</select>
</div>
<div className="campo-de-input">
<label>Data *</label>
<input
type="date"
name="dataAtendimento"
required
value={dadosAtendimento.dataAtendimento}
onChange={handleAtendimentoChange}
/>
</div>
</div>
<div className="campo-informacoes-atendimento">
<div className="campo-de-input">
<label>Início *</label>
<input
type="time"
name="inicio"
required
value={dadosAtendimento.inicio}
onChange={handleAtendimentoChange}
/>
</div>
<div className="campo-de-input">
<label>Término *</label>
<input
type="time"
name="termino"
required
value={dadosAtendimento.termino}
onChange={handleAtendimentoChange}
/>
</div>
<div className="campo-de-input">
<label>Profissional solicitante</label>
<select
name="solicitante"
value={dadosAtendimento.solicitante}
onChange={handleAtendimentoChange}
>
<option value="" disabled invisible selected>Selecione o solicitante</option>
<option value="secretaria">Secretária</option>
<option value="medico">Médico</option>
</select>
</div>
</div>
</section>
<section className="informacoes-atendimento-segunda-linha-direita">
<div className="campo-de-input">
<label>Observações</label>
<textarea
name="observacoes"
rows="4"
cols="1"
value={dadosAtendimento.observacoes}
onChange={handleAtendimentoChange}
></textarea>
</div>
</section>
</section>
<div className="form-actions">
<button type="submit" className="btn-primary">Salvar agendamento</button>
<button type="button" className="btn-cancel" onClick={onCancel}>Cancelar</button>
</div>
</form>
</div>
);
};
export default FormNovaConsulta;