436 lines
13 KiB
JavaScript
436 lines
13 KiB
JavaScript
import InputMask from "react-input-mask";
|
|
import "./style/formagendamentos.css";
|
|
import { useState, useEffect, useCallback } from "react";
|
|
import { GetPatientByCPF, GetAllPatients } from "../utils/Functions-Endpoints/Patient";
|
|
import { GetAllDoctors } from "../utils/Functions-Endpoints/Doctor";
|
|
import { useAuth } from "../utils/AuthProvider";
|
|
import API_KEY from "../utils/apiKeys";
|
|
|
|
|
|
const FormNovaConsulta = ({ onCancel, onSave, setAgendamento, agendamento }) => {
|
|
const { getAuthorizationHeader } = useAuth();
|
|
|
|
const [sessoes, setSessoes] = useState(1);
|
|
const [tempoBaseConsulta] = useState(30);
|
|
const [showSuccessModal, setShowSuccessModal] = useState(false);
|
|
const [todosProfissionais, setTodosProfissionais] = useState([]);
|
|
const [profissionaisFiltrados, setProfissionaisFiltrados] = useState([]);
|
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
const [horarioInicio, setHorarioInicio] = useState('');
|
|
const [horarioTermino, setHorarioTermino] = useState('');
|
|
const [horariosDisponiveis, sethorariosDisponiveis] = useState([]);
|
|
|
|
const [todosPacientes, setTodosPacientes] = useState([])
|
|
const [pacientesFiltrados, setPacientesFiltrados] = useState([])
|
|
const [isDropdownPacienteOpen, setIsDropdownPacienteOpen] = useState(false)
|
|
|
|
const [status, setStatus] = useState("confirmed")
|
|
|
|
let authHeader = getAuthorizationHeader()
|
|
|
|
const FormatCPF = (valor) => {
|
|
const digits = String(valor).replace(/\D/g, '').slice(0, 11);
|
|
return digits
|
|
.replace(/(\d{3})(\d)/, '$1.$2')
|
|
.replace(/(\d{3})(\d)/, '$1.$2')
|
|
.replace(/(\d{3})(\d{1,2})$/, '$1-$2');
|
|
};
|
|
|
|
const handleChange = (e) => {
|
|
const { value, name } = e.target;
|
|
|
|
if (name === 'email') {
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
contato: { ...prev.contato, email: value }
|
|
}));
|
|
} else if (name === 'status') {
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
status: prev.status === 'requested' ? 'confirmed' : 'requested'
|
|
}));
|
|
} else if (name === 'paciente_cpf') {
|
|
const cpfFormatted = FormatCPF(value);
|
|
const fetchPatient = async () => {
|
|
const patientData = await GetPatientByCPF(cpfFormatted, authHeader);
|
|
if (patientData) {
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
paciente_nome: patientData.full_name,
|
|
patient_id: patientData.id
|
|
}));
|
|
}
|
|
};
|
|
setAgendamento(prev => ({ ...prev, paciente_cpf: cpfFormatted }));
|
|
fetchPatient();
|
|
} else if (name === 'convenio') {
|
|
setAgendamento(prev => ({ ...prev, insurance_provider: value }));
|
|
} else {
|
|
setAgendamento(prev => ({ ...prev, [name]: value }));
|
|
}
|
|
};
|
|
|
|
const ChamarMedicos = useCallback(async () => {
|
|
const Medicos = await GetAllDoctors(authHeader);
|
|
setTodosProfissionais(Medicos);
|
|
}, [authHeader]);
|
|
|
|
const ChamarPacientes = useCallback (async () => {
|
|
const Pacientes = await GetAllPatients(authHeader);
|
|
setTodosPacientes(Pacientes)
|
|
console.log("pacientes")
|
|
console.log(Pacientes)
|
|
}, [authHeader])
|
|
|
|
useEffect(() => {
|
|
|
|
console.log("Horario","tessssste" )
|
|
if (agendamento?.scheduled_at) {
|
|
setHorarioInicio(formatarHora(agendamento.scheduled_at));
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
ChamarMedicos();
|
|
}, [ChamarMedicos]);
|
|
|
|
useEffect(() => {
|
|
|
|
ChamarPacientes()
|
|
}, [ChamarPacientes])
|
|
|
|
useEffect(() => {
|
|
if (!agendamento.dataAtendimento || !agendamento.doctor_id) return;
|
|
|
|
const myHeaders = new Headers();
|
|
myHeaders.append("Content-Type", "application/json");
|
|
myHeaders.append("apikey", API_KEY);
|
|
myHeaders.append("Authorization", `Bearer ${authHeader.split(' ')[1]}`);
|
|
|
|
const raw = JSON.stringify({
|
|
doctor_id: agendamento.doctor_id,
|
|
start_date: agendamento.dataAtendimento,
|
|
end_date: `${agendamento.dataAtendimento}T23:59:59.999Z`,
|
|
});
|
|
|
|
const requestOptions = {
|
|
method: 'POST',
|
|
headers: myHeaders,
|
|
body: raw,
|
|
};
|
|
|
|
fetch("https://yuanqfswhberkoevtmfr.supabase.co/functions/v1/get-available-slots", requestOptions)
|
|
.then(response => response.json())
|
|
.then(result => sethorariosDisponiveis(result))
|
|
.catch(error => console.log('error', error));
|
|
}, [agendamento.dataAtendimento, agendamento.doctor_id, authHeader]);
|
|
|
|
const handleSearchProfissional = (e) => {
|
|
const term = e.target.value;
|
|
handleChange(e);
|
|
|
|
if (term.trim() === '') {
|
|
setProfissionaisFiltrados([]);
|
|
setIsDropdownOpen(false);
|
|
return;
|
|
}
|
|
|
|
const filtered = todosProfissionais.filter(p =>
|
|
p.full_name.toLowerCase().includes(term.toLowerCase())
|
|
);
|
|
|
|
setProfissionaisFiltrados(filtered);
|
|
setIsDropdownOpen(filtered.length > 0);
|
|
};
|
|
|
|
const handleSearchPaciente = (e) => {
|
|
const term = e.target.value;
|
|
handleChange(e);
|
|
|
|
if (term.trim() === '') {
|
|
setPacientesFiltrados([]);
|
|
setIsDropdownPacienteOpen(false);
|
|
return;
|
|
}
|
|
|
|
const filtered = todosPacientes.filter(p =>
|
|
p.full_name.toLowerCase().includes(term.toLowerCase())
|
|
);
|
|
console.log(filtered.length > 0, "filtrados")
|
|
|
|
setPacientesFiltrados(filtered);
|
|
setIsDropdownPacienteOpen(filtered.length > 0);
|
|
}
|
|
|
|
const handleSelectProfissional = (profissional) => {
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
doctor_id: profissional.id,
|
|
nome_medico: profissional.full_name
|
|
}));
|
|
setProfissionaisFiltrados([]);
|
|
setIsDropdownOpen(false);
|
|
};
|
|
|
|
const handleSelectPaciente = (paciente) => {
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
patient_id:paciente.id,
|
|
paciente_nome: paciente.full_name,
|
|
paciente_cpf: paciente.cpf
|
|
}))
|
|
setProfissionaisFiltrados([])
|
|
setIsDropdownPacienteOpen(false)
|
|
|
|
}
|
|
|
|
const formatarHora = (datetimeString) => {
|
|
return datetimeString?.substring(11, 16) || '';
|
|
};
|
|
|
|
const opcoesDeHorario = horariosDisponiveis?.slots?.map(item => ({
|
|
value: formatarHora(item.datetime),
|
|
label: formatarHora(item.datetime),
|
|
disabled: !item.available
|
|
})) || [];
|
|
|
|
const calcularHorarioTermino = useCallback((inicio, sessoes, tempoBase) => {
|
|
if (!inicio || inicio.length !== 5 || !inicio.includes(':')) return '';
|
|
|
|
const [horas, minutos] = inicio.split(':').map(Number);
|
|
const minutosInicio = (horas * 60) + minutos;
|
|
const duracaoTotalMinutos = sessoes * tempoBase;
|
|
const minutosTermino = minutosInicio + duracaoTotalMinutos;
|
|
|
|
const horaTermino = Math.floor(minutosTermino / 60) % 24;
|
|
const minutoTermino = minutosTermino % 60;
|
|
|
|
const formatar = (num) => String(num).padStart(2, '0');
|
|
return `${formatar(horaTermino)}:${formatar(minutoTermino)}`;
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const novoTermino = calcularHorarioTermino(horarioInicio, sessoes, tempoBaseConsulta);
|
|
setHorarioTermino(novoTermino);
|
|
setAgendamento(prev => ({
|
|
...prev,
|
|
horarioTermino: novoTermino
|
|
}));
|
|
}, [horarioInicio, sessoes, tempoBaseConsulta, setAgendamento, calcularHorarioTermino]);
|
|
|
|
const handleSubmit = (e) => {
|
|
e.preventDefault();
|
|
setShowSuccessModal(true);
|
|
};
|
|
|
|
const handleCloseModal = () => {
|
|
setShowSuccessModal(false);
|
|
onSave({ ...agendamento, horarioInicio: horarioInicio, status:status });
|
|
};
|
|
|
|
const handleCheckbox = () => {
|
|
if(status === "confirmed"){
|
|
setStatus("requested")
|
|
}else{
|
|
setStatus("confirmed")
|
|
}
|
|
|
|
}
|
|
|
|
return (<div className="form-container">
|
|
{showSuccessModal && (
|
|
<div className="modal-overlay">
|
|
<div className="modal-content">
|
|
<div className="modal-header">
|
|
<h5 className="modal-title">Sucesso</h5>
|
|
</div>
|
|
<div className="modal-body">
|
|
<p className="modal-message">Agendamento salvo com sucesso!</p>
|
|
</div>
|
|
<div className="modal-footer">
|
|
<button onClick={handleCloseModal} className="modal-confirm-btn">Fechar</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<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-container">
|
|
<div className="campo-de-input">
|
|
<label>Nome *</label>
|
|
<input
|
|
type="text"
|
|
name="paciente_nome"
|
|
placeholder="Insira o nome do paciente"
|
|
required
|
|
onChange={(e) => handleSearchPaciente(e)}
|
|
value={agendamento?.paciente_nome || ""}
|
|
autoComplete="off"
|
|
/>
|
|
</div>
|
|
{isDropdownPacienteOpen && pacientesFiltrados.length > 0 && (
|
|
<div className="dropdown-pacientes">
|
|
{pacientesFiltrados.map((paciente) => (
|
|
<div
|
|
key={paciente.id}
|
|
className="dropdown-item"
|
|
onClick={() => handleSelectPaciente(paciente)}
|
|
>
|
|
{`${paciente.full_name.split(" ")[0]} ${paciente.full_name.split(" ")[1]} - ${paciente.cpf}`}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="campo-de-input campo-cpf">
|
|
<label>CPF do paciente</label>
|
|
<input
|
|
type="text"
|
|
name="paciente_cpf"
|
|
placeholder="000.000.000-00"
|
|
onChange={handleChange}
|
|
value={agendamento.paciente_cpf}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="campos-informacoes-paciente" id="informacoes-paciente-linha-tres">
|
|
<div>
|
|
<label>Convênio</label>
|
|
<select name="convenio" onChange={handleChange} value={agendamento.insurance_provider}>
|
|
<option value="publico">Público</option>
|
|
<option value="unimed">Unimed</option>
|
|
<option value="bradesco_saude">Bradesco Saúde</option>
|
|
<option value="hapvida">Hapvida</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<h2 className="section-title">Informações do atendimento</h2>
|
|
|
|
<div className="campo-informacoes-atendimento">
|
|
<div className="campo-de-input-container">
|
|
<div className="campo-de-input">
|
|
<label>Nome do profissional *</label>
|
|
<input
|
|
type="text"
|
|
name="nome_medico"
|
|
onChange={handleSearchProfissional}
|
|
value={agendamento?.nome_medico || ''}
|
|
autoComplete="off"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
{isDropdownOpen && profissionaisFiltrados.length > 0 && (
|
|
<div className="dropdown-profissionais">
|
|
{profissionaisFiltrados.map((profissional) => (
|
|
<div
|
|
key={profissional.id}
|
|
className="dropdown-item"
|
|
onClick={() => handleSelectProfissional(profissional)}
|
|
>
|
|
{profissional.full_name}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="tipo_atendimento">
|
|
<label>Tipo de atendimento *</label>
|
|
<select name="tipo_atendimento" onChange={handleChange} value={agendamento.tipo_atendimento}>
|
|
<option value="presencial">Presencial</option>
|
|
<option value="teleconsulta">Teleconsulta</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<section id="informacoes-atendimento-segunda-linha">
|
|
<div className="campo-informacoes-atendimento">
|
|
<div className="campo-de-input">
|
|
<label>Data *</label>
|
|
<input
|
|
type="date"
|
|
name="dataAtendimento"
|
|
onChange={handleChange}
|
|
value={agendamento.dataAtendimento}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="linha">
|
|
<div className="campo-de-input">
|
|
<label htmlFor="inicio">Início *</label>
|
|
<select
|
|
id="inicio"
|
|
name="inicio"
|
|
required
|
|
value={horarioInicio}
|
|
onChange={(e) => setHorarioInicio(e.target.value)}
|
|
>
|
|
<option value="" disabled>Selecione a hora de início</option>
|
|
{opcoesDeHorario.map((opcao, index) => (
|
|
<option key={index} value={opcao.value} disabled={opcao.disabled}>
|
|
{opcao.label}
|
|
{opcao.disabled && " (Indisponível)"}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="campo-de-input">
|
|
<label htmlFor="termino">Término *</label>
|
|
<input
|
|
type="text"
|
|
id="termino"
|
|
name="termino"
|
|
value={horarioTermino || '— —'}
|
|
readOnly
|
|
className="horario-termino-readonly"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="campo-de-input observacoes">
|
|
<label>Observações</label>
|
|
<textarea
|
|
name="observacoes"
|
|
rows="4"
|
|
cols="1"
|
|
onChange={handleChange}
|
|
value={agendamento.observacoes || ''}
|
|
/>
|
|
</div>
|
|
</section>
|
|
|
|
<div className="campo-de-input-check">
|
|
<input
|
|
className="form-check-input form-custom-check"
|
|
type="checkbox"
|
|
name="status"
|
|
onChange={handleCheckbox}
|
|
checked={status === "requested"}
|
|
/>
|
|
<label className="form-check-label checkbox-label" htmlFor="status">
|
|
Adicionar à fila de espera
|
|
</label>
|
|
</div>
|
|
|
|
<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;
|