359 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. 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, useCallback } from "react";
import { GetPatientByCPF } 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 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]);
useEffect(() => {
ChamarMedicos();
}, [ChamarMedicos]);
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 handleSelectProfissional = (profissional) => {
setAgendamento(prev => ({
...prev,
doctor_id: profissional.id,
nome_medico: profissional.full_name
}));
setProfissionaisFiltrados([]);
setIsDropdownOpen(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 });
};
return (
<div className="form-container">
{showSuccessModal && (
<div className="modal-overlay">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Sucesso</h5>
<button onClick={handleCloseModal} className="modal-close-btn">×</button>
</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">
<label>CPF do paciente</label>
<input type="text" name="paciente_cpf" placeholder="000.000.000-00" onChange={handleChange} value={agendamento.paciente_cpf}/>
</div>
<div className="campo-de-input">
<label>Nome *</label>
<input type="text" name="paciente_nome" value={agendamento.paciente_nome} placeholder="Insira o nome do paciente" required onChange={handleChange} />
</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 onChange={handleChange} name="tipo_atendimento" value={agendamento.tipo_atendimento}>
<option value="presencial">Presencial</option>
<option value="teleconsulta">Teleconsulta</option>
</select>
</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>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='seletor-wrapper'>
<label>Número de Sessões *</label>
<div className='sessao-contador'>
<button
type="button"
onClick={() => setSessoes(prev => Math.max(0, prev - 1))}
disabled={sessoes === 0}
>
<i className="bi bi-chevron-compact-left"></i>
</button>
<p className='sessao-valor'>{sessoes}</p>
<button
type="button"
onClick={() => setSessoes(prev => Math.min(3, prev + 1))}
disabled={sessoes === 3}
>
<i className="bi bi-chevron-compact-right"></i>
</button>
</div>
</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>
</section>
<section className="informacoes-atendimento-segunda-linha-direita">
<div className="campo-de-input">
<label>Observações</label>
<textarea name="observacoes" rows="4" cols="1" onChange={handleChange} value={agendamento.observacoes || ''}></textarea>
</div>
</section>
</section>
<div className="campo-de-input-check">
<input
className="form-check-input form-custom-check"
type="checkbox"
name="status"
onChange={handleChange}
checked={agendamento.status === 'requested'}
/>
<label className="form-check-label checkbox-label" htmlFor="status">
Adicionar a 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;